7

psycopg2 を使用していますが、イベント (実行されたクエリ、通知、エラー) をファイルに記録する際に問題があります。PgAdminの履歴ウィンドウのように効果を出したい。

たとえば、次のクエリを実行しています。

insert into city(id, name, countrycode, district, population) values (4080,'Savilla', 'ESP', 'andalucia', 1000000)

PgAdmin では、次のような効果が見られます。

Executing query: 
insert into city(id, name, countrycode, district, population) values (4080,'Sevilla', 'ESP', 'andalucia', 1000000)

Query executed in 26 ms.
One row affected.

psycopg2 を使用して同様の効果を得ることができますか?

LoggingCursorを使用しようとしましたが、クエリのみをログに記録するため、満足のいくものではありませんでした。

手伝ってくれてありがとう。


編集:

私のコード:

conn = psycopg2.extras.LoggingConnection(DSN)
File=open('log.log','a')
File.write('================================')
psycopg2.extras.LoggingConnection.initialize(conn,File)

File.write('\n'+time.strftime("%Y-%m-%d %H:%M:%S") + '---Executing query:\n\t')
q="""insert into city(id, name, countrycode, district, population) values (4080,'Sevilla', 'ESP', 'andalucia', 10000)"""
c=conn.cursor()
c.execute(q)
File.write('\n'+time.strftime("%Y-%m-%d %H:%M:%S") + '---Executing query:\n\t')
q="""delete from city where id = 4080"""
c=conn.cursor()
c.execute(q)
conn.commit()
File.close()

そして、これは私の出力ログです:

================================
2012-12-30 22:42:31---Executing query:
    insert into city(id, name, countrycode, district, population) values (4080,'Sevilla', 'ESP', 'andalucia', 10000)

2012-12-30 22:42:31---Executing query:
    delete from city where id = 4080

影響を受けた行数とエラーに関する情報をログ ファイルで確認したいと考えています。最後に、すべてのイベントを含む完全なログ ファイルが必要です。

4

3 に答える 3

4

私が見る限り、LoggingCursor クラスでは満たされない要件が 3 つあります。

  1. クエリ実行時間
  2. 影響を受ける行数
  3. すべてのイベントを含む完全なログ ファイル。

最初の要件については、psycopg2.extras のMinTimeLoggingConnectionクラスのソース コードを見てください。これは LoggingConnection をサブクラス化し、最小時間を超えるクエリの実行時間を出力します (これは MinTimeLoggingCursor と組み合わせて使用​​する必要があることに注意してください)。

2 番目の要件については、カーソル クラスのrowcount 属性が指定します。

最後の execute*() によって生成された (SELECT などの DQL ステートメントの場合) または影響を受けた (UPDATE や INSERT などの DML ステートメントの場合) 行の数

したがって、この追加機能を含む独自のタイプの LoggingConnection および LoggingCursor を作成できるはずです。

私の試みは次のとおりです。コード内で を置き換えるだけLoggingConnectionで、これはすべて機能するはずです。LoggingConnection2補足として、2 番目のクエリ用に新しいカーソルを作成する必要はありません。c.execute(q)2 番目のクエリを定義した後、もう一度呼び出すことができます。

import psycopg2
import os
import time
from psycopg2.extras import LoggingConnection
from psycopg2.extras import LoggingCursor

class LoggingConnection2(psycopg2.extras.LoggingConnection):
    def initialize(self, logobj):
        LoggingConnection.initialize(self, logobj)

    def filter(self, msg, curs):
        t = (time.time() - curs.timestamp) * 1000
        return msg + os.linesep + 'Query executed in: {0:.2f} ms. {1} row(s) affected.'.format(t, curs.rowcount)

    def cursor(self, *args, **kwargs):
        kwargs.setdefault('cursor_factory', LoggingCursor2)
        return super(LoggingConnection, self).cursor(*args, **kwargs)

class LoggingCursor2(psycopg2.extras.LoggingCursor):    
    def execute(self, query, vars=None):
        self.timestamp = time.time()
        return LoggingCursor.execute(self, query, vars)

    def callproc(self, procname, vars=None):
        self.timestamp = time.time()
        return LoggingCursor.execute(self, procname, vars)

すべてのイベントの完全なログを作成する方法はわかりませんが、接続クラスの通知属性は興味深いかもしれません。

于 2012-12-30T23:06:42.863 に答える
0

LoggingCursor がどのように実装されているかを見て、独自のカーソル サブクラスを作成してください。非常に簡単です。

于 2013-01-09T15:17:59.513 に答える