我想通过安装audittrail模块来管理OpenERP用户的活动
创建一些规则(定义哪个用户,哪个对象以及将监视哪个活动(创建,更新...))。我更新了一个产品,看它是否有效
当我尝试更新产品时,我遇到了系统错误。看到日志,我得到了
[2010-08-31 12:53:35,042]光标未明确关闭
[2010-08-31 12:53:35,043]光标创建于/home/pilgrim/working/sources/addons/audittrail/audittrail.py:204
这里导致错误的行
cr = pooler.get_db(db)。cursor()
看一下sql_db.py,我收到了评论
def __del__(self):
if not self.__closed:
# Oops. 'self' has not been closed explicitly.
# The cursor will be deleted by the garbage collector,
# but the database connection is not put back into the connection
# pool, preventing some operation on the database like dropping it.
# This can also lead to a server overload.
msg = "Cursor not closed explicitly\n" \
"Cursor was created at %s:%s" % self.__caller
log(msg, netsvc.LOG_WARNING)
self.close()
由于我是Python的新手,我不知道如何克服这个问题? 有什么暗示可以克服这个问题吗? 感谢
答案 0 :(得分:4)
cr = sqldb.db_connect(dbname).cursor()
.........
cr.close()
cr = None
我建议您破解audittrail.py以查找创建光标的位置以及关闭它们的位置。一个典型的问题是异常处理错误,导致代码跳过正常的闭包。
尝试在可疑的游标操作周围放置一个try,except和finally子句。这应该可以帮助你解决问题。
答案 1 :(得分:2)
我想我找到了答案。 查看示例
def a():
try:
print 'before return '
return 1
finally:
print 'in finally'
拨打()
before return
in finally
1
这很正常。好。 尝试另一个例子(来自audittrail.py的代码提取)
def do_something_with_db(db):
// open cusror again
cr = db.cursor()
// do somethign
// close cursor internally
cr.close()
def execute(db)
// 1, open connection and open cursor
cr = db.cursor
try:
//2, do something with db, seeing that this method will open cursor again
return do_something_with_db(db)
finally:
cr.close()
看到do_something_with_db的实现尝试打开游标(可以称为连接),但当前的一个没有显式关闭。 所以解决方案很简单:将当前的cr传递给
Before
**do_something_with_db(db)**
after
**do_something_with_db(cr)**
现在错误消失了。
@Don Kirkby:是的,我们应该尝试尝试......终于
答案 2 :(得分:1)
您可以在PyDev plug in的Eclipse之类的调试器中运行OpenERP吗?我发现追踪问题的最有效方法。我没有使用审计跟踪模块,但是我快速查看了source code,看来光标正在log_fct()
的开头附近打开。 (我原以为它会报告第207行,你正在运行哪个版本?)以下是我认为的相关代码:
def log_fct(self, db, uid, passwd, object, method, fct_src, *args):
logged_uids = []
pool = pooler.get_pool(db)
cr = pooler.get_db(db).cursor() # line 207 in version 5.0.12
# ...
if method in ('create'):
# ...
cr.close()
return res_id
# ...
cr.close()
看起来方法中有几个return语句,但是每个语句似乎都先调用cr.close()
,所以我没有看到任何明显的问题。尝试在此方法中使用断点在调试器中运行它。如果这不可能,您可以尝试使用以下内容写入日志:
logger = netsvc.Logger()
logger.notifyChannel('audittrail', netsvc.LOG_INFO, 'something happened')
<强>更新强>
你评论说这是在重负荷下发生的。可能抛出异常并且光标未被关闭。您可以使用try
... finally
statement来确保光标始终关闭。以下是转换后上面示例的样子:
def log_fct(self, db, uid, passwd, object, method, fct_src, *args):
logged_uids = []
pool = pooler.get_pool(db)
cr = pooler.get_db(db).cursor() # line 207 in version 5.0.12
try:
# ...
if method in ('create'):
# ...
return res_id
# ...
finally:
cr.close()