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?
>>>
>>>

Reply via email to