2

質問にこの見出しを付けるのは嫌いですが、実際には何が起こっているのかわかりません。

ロギングモジュールを使用したい別のプロジェクトを行っていました。コードはいくつかのファイルに分散されており、個別のファイル用に個別のロガー オブジェクトを作成する代わりに、コンテンツを含む logs.py を作成することを考えました

import sys, logging

class Logger:
    def __init__(self):
        formatter = logging.Formatter('%(filename)s:%(lineno)s %(levelname)s:%(message)s')
        stdout_handler = logging.StreamHandler(sys.stdout)
        stdout_handler.setFormatter(formatter)
        self.logger=logging.getLogger('')
        self.logger.addHandler(stdout_handler)
        self.logger.setLevel(logging.DEBUG)

    def debug(self, message):
        self.logger.debug(message)

このクラスを(別のファイルで)使用します。

import logs
b = logs.Logger()
b.debug("Hi from a.py")
  1. ここで質問するために、問題全体を取り除きました。現在、a.py、b.py、main.py の 3 つのファイルがあります。3 つのファイルはすべて、logs.Logger クラスをインスタンス化し、デバッグ メッセージを出力します。
  2. a.py & b.pyは「ログ」をインポートし、デバッグ メッセージを出力します。
  3. main.pyインポート ログ、a & b ; 独自のデバッグ メッセージを出力します。

ファイルの内容は次のとおりです: http://i.imgur.com/XoKVf.png

b.py からのデバッグ メッセージが 2 回出力され、main.py から 3 回出力されるのはなぜですか?

4

3 に答える 3

2

ロガーの名前を指定します。名前を指定しない場合は、常にルートロガーを使用します。

import sys, logging

class Logger:
    def __init__(self, name):
        formatter = logging.Formatter('%(filename)s:%(lineno)s %(levelname)s:%(message)s')
        stdout_handler = logging.StreamHandler(sys.stdout)
        stdout_handler.setFormatter(formatter)
        self.logger=logging.getLogger(name)
        self.logger.addHandler(stdout_handler)
        self.logger.setLevel(logging.DEBUG)

    def debug(self, message):
        self.logger.debug(message)

http://docs.python.org/howto/logging.html#advanced-logging-tutorial

ロガーに名前を付けるときに使用する良い規則は、次のように名前が付けられた、ロギングを使用する各モジュールでモジュールレベルのロガーを使用することです。

logger = logging.getLogger(__name__)

于 2011-09-27T10:01:46.213 に答える
2

logging.getLogger('')呼び出すたびにまったく同じオブジェクトが返されます。したがって、インスタンス化するたびにLogger(なぜここで古いスタイルのクラスを使用するのですか?)、もう1つのハンドラーをアタッチして、もう1つのターゲットに出力します。すべてのターゲットが同じものを指しているので、最後の呼び出しは、を指している3つのオブジェクト.debug()のそれぞれに印刷され、3行が印刷されます。StreamHandlersys.stdout

于 2011-09-27T10:00:55.540 に答える
1

初め。の独自のクラスを作成しないでくださいLogger

logging既存の構成ツールを使用して、既存のロガー クラスを構成するだけです。

2番。独自のクラスを作成するたびに、Logger新しいハンドラーも作成し、新しい (複製する) ハンドラーをルート ロガーにアタッチします。これにより、メッセージの重複が発生します。

(1) スタンドアロンで実行し、(2) より大きな複合アプリケーションの一部としても実行する必要がある複数のモジュールがある場合は、これを行う必要があります。これにより、ロギング構成が 1 回だけ行われることが保証されます。

import logging
logger= logging.getLogger( __file__ ) # Unique logger for a, b or main


if __name__ == "__main__":
    logging.basicConfig( stream=sys.stdout, level=logging.DEBUG, format='%(filename)s:%(lineno)s %(levelname)s:%(message)s' )
    # From this point forward, you can use the `logger` object.
    logger.info( "Hi" )
于 2011-09-27T10:01:07.623 に答える