web-dev-qa-db-ja.com

Python logging.basicConfigを実行する前にロギングしますか?

Logging.info()[〜#〜] before [〜#〜]を呼び出してlogging.basicConfigを実行した場合、logging.basicConfig呼び出しは効果がないようです。実際、ロギングは発生しません。

この動作はどこに文書化されていますか?よくわかりません。

45
Joseph Turian

デフォルトのハンドラーを削除して、次のようにログを再構成できます。

# if someone tried to log something before basicConfig is called, Python creates a default handler that
# goes to the console and will ignore further basicConfig calls. Remove the handler if there is one.
root = logging.getLogger()
if root.handlers:
    for handler in root.handlers:
        root.removeHandler(handler)
logging.basicConfig(format='%(asctime)s %(message)s',level=logging.DEBUG)
47

はい。

あなたは何かを記録するように頼んだ。したがって、ロギングはデフォルト構成を作成する必要があります。ロギングが構成されると...まあ...それは構成されます。

「ロガーオブジェクトを構成した状態で、次のメソッドがログメッセージを作成します。」

さらに、誤ったロギングを防ぐためのハンドラーの作成について読むことができます。しかし、それは有用な手法というよりも、悪い実装のハックです。

これにはトリックがあります。

  1. モジュールは、グローバルレベルでlogging.getlogger()リクエスト以外は何もできません。

  2. だけ if __== "__main__":ログ設定を行うことができます。

モジュールでグローバルレベルでロギングを行う場合は、ロギングにデフォルト構成を作成させることができます。

しないでくださいlogging.info任意のモジュールでグローバルに。あなたが絶対にあなたが持っている必要があると思うならlogging.infoモジュールのグローバルレベルで、ロギングを構成する必要がありますbeforeインポートを実行します。これは、見栄えの悪いスクリプトにつながります。

10
S.Lott

Carlos A. Ibarraからのこの回答は原則として正しいですが、removeHandler()を呼び出すことによって変更される可能性のあるリストを反復処理しているため、実装が失敗する可能性があります。これは安全ではありません。 2つの選択肢は次のとおりです。

while len(logging.root.handlers) > 0:
    logging.root.removeHandler(logging.root.handlers[-1])
logging.basicConfig(format='%(asctime)s %(message)s',level=logging.DEBUG)

または:

logging.root.handlers = []
logging.basicConfig(format='%(asctime)s %(message)s',level=logging.DEBUG)

ここで、ループを使用するこれら2つの最初のものが最も安全です(ハンドラーの破棄コードは、ロギングフレームワーク内で明示的に呼び出すことができるため)。それでも、logging.root.handlersをリストとして使用しているため、これはハックです。

8
Paul Kremer

これが上記の回答で言及されていないパズルの一部です...そしてそれはすべて理にかなっています:「ルート」ロガー-ロギングの前にlogging.info()を呼び出す場合に使用されます。 basicConfig(level = logging.DEBUG)--デフォルトのログレベルはWARNINGです

そのため、logging.info()とlogging.debug()は何もしません。構成したのでnot to、by ... um ...構成していません。

おそらく関連しています(これは私を少し噛みました):basicConfigを呼び出さないとき、ハンドラーをDEBUGレベルに設定しても、デバッグメッセージが表示されないようです。少し髪を引っ張った後、カスタムのレベルを設定する必要があることがわかりましたlogger同様にDEBUGになります。ロガーがWARNINGに設定されている場合、ハンドラーを(単独で)DEBUGに設定しても、logger.info()およびlogger.debug()の出力は取得されません。

5
Dan H