3

我想通过安装 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 新手,我不知道如何克服这个问题?
有什么提示可以克服这个吗?
感谢

4

3 回答 3

4

查看源代码以了解发生了什么很重要。但是从您发布的内容来看,之前的游标似乎没有明确关闭。

cr = sqldb.db_connect(dbname).cursor()
.........
cr.close()
cr = None

我建议您破解 audittrail.py 以查找创建光标的位置以及关闭光标的位置。一个典型的问题是对异常的错误处理,导致代码跳过正常的闭包。

尝试在有问题的游标操作周围放置一个 try、except 和 finally 子句。这应该可以帮助您解决问题。

于 2010-08-31T07:14:03.900 回答
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:是的,我们应该尝试尝试……最后

于 2010-10-06T10:42:10.853 回答
1

你能在像Eclipse的PyDev 插件这样的调试器中运行 OpenERP吗?我发现这是追踪问题的最有效方法。我没有使用审计跟踪模块,但我快速查看了源代码,并且似乎在. (我原以为它会报告第 207 行,您正在运行哪个版本?)这是我认为的相关代码:log_fct()

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 语句来确保游标始终处于关闭状态。以下是上面的示例在转换后的样子:

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()
于 2010-09-01T22:33:40.487 回答