Think the combination of persistant logger object and SQLite threading issues makes this too hard (couldn't get it working with commit() either)- I'll look for a simpler solution.
(PS- For non web2py-DAL sqlite logging, I stumbled upon a thread safe class I built a while back- still works, in case anyone's interested: SQLiteHandler <https://gist.github.com/2662203#file_sqlite_handler.py>) On Friday, May 11, 2012 6:07:30 PM UTC-4, Massimo Di Pierro wrote: > > After > > self.log_db.log.insert(**args) > > you need > > self.log_db.commit() > > every http request, the models, are executed, DAL(...) connects you to the > db (or recycles a connection from the pool), then when the action is done, > it automatically commits or rollsback, then web2py closes the connection. > > If you import a module, Python caches the module. A db connection defined > in the module, lives as long as the module lives. A db connection defined > in a model lives only as long as the http request lives. If you pass one to > the other you run into trouble. > > One more complication is that if you use sqlite, if one process/thread > opens the file and tries write into it, the file gets locked. > > > > On Friday, 11 May 2012 15:40:39 UTC-5, Yarin wrote: >> >> Massimo- see revised - this is one model file and now I'm defining the db >> in the constructor, but I get the "Cannot operate on a closed database" >> error immediately. >> >> >> import logging >> import logging.handlers >> >> class AppHandler(logging.Handler): # Inherit from logging.Handler >> def __init__(self): >> logging.Handler.__init__(self) >> >> self.log_db = DAL('sqlite://log.sqlite') >> self.log_db.define_table('log', >> Field('loggername', 'string'), >> Field('srclineno', 'string'), >> Field('func', 'string'), >> Field('level', 'string'), >> Field('msg', 'string'), >> Field('type', 'string') >> ) >> >> def emit(self, record): >> >> args = {} >> args['loggername'] = record.name >> args['srclineno'] = record.lineno >> args['func'] = record.funcName >> args['level'] = record.levelname >> args['msg'] = record.msg >> try: >> args['type'] = record.args[0] >> except: >> args['type'] = None >> >> self.log_db.log.insert(**args) >> >> logger = logging.getLogger("web2py.app.myapp") >> logger.setLevel(logging.DEBUG) >> logger.addHandler(AppHandler()) >> logger.debug('test log') >> >> >> >> >> Are you saying I need to make a connection and commit manually? How come >> this isn't required in the normal db.py file's db definition- there we just >> define it and go? >> >> On Friday, May 11, 2012 4:19:22 PM UTC-4, Massimo Di Pierro wrote: >>> >>> Is this one or two files? >>> >>> If the model is passing db to the logger then the db is closed when the >>> first request responds. >>> The logger must make its own connection to the db and commit >>> >>> On Friday, 11 May 2012 14:28:22 UTC-5, Yarin wrote: >>>> >>>> Here is my complete model code for a sqlite logging handler. This works >>>> the first time the program is run, and after that I get an error: >>>> >>>> <class 'sqlite3.ProgrammingError'> Cannot operate on a closed database. >>>> >>>> >>>> *model mylogging.py:* >>>> >>>> import logging >>>> import logging.handlers >>>> >>>> >>>> class AppHandler(logging.Handler): # Inherit from logging.Handler >>>> def __init__(self): >>>> logging.Handler.__init__(self) >>>> >>>> self._db = db >>>> >>>> >>>> def emit(self, record): >>>> >>>> args = {} >>>> args['loggername'] = record.name >>>> args['srclineno'] = record.lineno >>>> args['func'] = record.funcName >>>> args['level'] = record.levelname >>>> args['msg'] = record.msg >>>> try: >>>> args['type'] = record.args[0] >>>> except: >>>> args['type'] = None >>>> >>>> self._db.log.insert(**args) >>>> >>>> >>>> >>>> >>>> log_db = DAL('sqlite://log.sqlite') >>>> log_db.define_table('log', >>>> >>>> Field('loggername', 'string'), #unique=True >>>> Field('srclineno', 'string'), >>>> Field('func', 'string'), >>>> Field('level', 'string'), >>>> Field('msg', 'string'), >>>> Field('type', 'string'), >>>> ) >>>> >>>> >>>> import logging >>>> logger = logging.getLogger("web2py.app.myapp") >>>> logger.setLevel(logging.DEBUG) >>>> >>>> >>>> logger.addHandler(AppHandler(log_db)) >>>> logger.debug('test log') >>>> >>>> >>>> >>>> I don't understand how I'm causing this, as all as im doing is creating >>>> a second db instance and inserting using web2py DAL methods? >>>> >>>>

