3

audittrail モジュールをインストールして、OpenERP ユーザーのアクティビティを管理したいと考えています。
いくつかのルールを作成した後 (監視するユーザー、オブジェクト、およびアクティビティ (作成、更新など) を定義します)。製品が機能することを確認するために製品を更新します。
製品を更新しようとしたときに、システム エラーが発生しました。ログを見ると、
[2010-08-31 12:53:35,042] カーソルが明示的に閉じられていません
[2010-08-31 12:53:35,043] Cursor was created at /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'

a() を呼び出す

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 に答える