2011-07-27 6 views
9

ロギングメッセージフォーマットを一時的に変更する最も簡単な方法は、Pythonでは(ロギングモジュールを介して)何ですか?Pythonでログに記録されたメッセージのフォーマットを一時的に変更するには?

目的は、標準的なメッセージフォーマットを使用し、読み込み中のファイルに関する情報(名前など)を一時的に追加できるようにすることです。ファイルがもう読み込まれていないときは、メッセージ形式はデフォルトに戻されます。メッセージを生成するプログラムはであり、はどのファイルが読み込まれているかを認識していないため、メッセージに関連するファイル名が自動的に含まれているとエラーメッセージが表示されます(エラーメッセージは " ***: ... "の代わりに" ... ")。

+0

私は自分の答えを更新しました。 –

答えて

7

ここには、Vinay Sajip自身のHOWTOから推測できる簡単な解決策があります。それは基本的にsetFormatter()でログフォーマッタを更新:

import logging 

logger = logging.getLogger() # Logger 
logger_handler = logging.StreamHandler() # Handler for the logger 
logger.addHandler(logger_handler) 

# First, generic formatter: 
logger_handler.setFormatter(logging.Formatter('%(message)s')) 
logger.error('error message') # Test 

# New formatter for the handler: 
logger_handler.setFormatter(logging.Formatter('PROCESSING FILE xxx - %(message)s')) 
logger.error('error message') # Test 

これは正しく生成します。

error message 
PROCESSING FILE xxx - error message 

(問題のために尋ねたよう xxxをファイルに動的に設定することができ、処理されています)。

+0

これが解決策である理由は分かりません。ハンドラがログの宛先を決定し、フォーマッタがログ形式を決定します。これら2つは直交していると考えることができる。モジュール固有のコンテキスト情報を追加するために、特定のロガー(logger 'package1.module2'など)のログフォーマットを一時的に変更したい場合は、ロガーのすべてのハンドラに対して*このようにします。他のすべてのロガーでよく使われるハンドラーを列挙し、一時的にフォーマットを変更した後、他のロガーを壊さないように変更することは解決策ではありません。 – dtheodor

+0

これは実際には、ハンドラーがロガーの中でどのように配布されるかをほとんど制御していないこの極端な状況で行われなければならないことです。これは特定かつ不幸なケースです。さて、これを行うことはまだこの答えに従って行うことができますので、私にはうまく見えます(免責事項:私は両方の質問をし、この答えを提供しました)。興味深いのは、上記のコメントのケースアウトラインに固有の質問とそれに対応する具体的な回答を持つことです。これは別のStackOverflowエントリに属します。 – EOL

6

いくつかの方法があります。 、Filterなど、already documented ones(ログ呼び出しの引数はextra)以外に、独自の書式設定クラスを指定する方法もあります。このカスタム書式設定クラスでは、処理中のファイルについての情報を保持できます。たとえば、次のように

class FileProcessingFormatter(logging.Formatter): 
    def __init__(self, fmt, datefmt=None, current_file=None): 
     super(FileProcessingFormatter, self).__init__(fmt, datefmt) 
     self.orig_fmt = fmt 
     self.current_file = current_file 

    def format(self, record): 
     if self.current_file is None: 
      self._fmt = self.orig_fmt.replace('__FILE_PLACEHOLDER__', '') 
     else: 
      self._fmt = self.orig_fmt.replace('__FILE_PLACEHOLDER__', 
          ' while processing %r' % self.current_file) 
     return super(FileProcessingFormatter, self).format(record) 

インスタンス化フォーマッタ...

f = FileProcessingFormatter('%(levelname)s__FILE_PLACEHOLDER__ %(message)s') 
for h in relevant_handlers: 
    h.setFormatter(f) 

プロセスファイル...

f.current_file = fn 
process_file(fn) 
f.current_file = None 

これは非常に単純である - 例えば、ないスレッド環境での使用のためにならばファイル処理は異なるスレッドによって同時に行われます。

アップデート:ルートロガーのハンドラはlogging.getLogger().handlersでアクセスできますが、これは変更可能な実装の詳細です。要件が基本的ではないため、dictConfig()を使用してログを構成できます(logutilsプロジェクトの古いバージョンのPythonで利用可能)。

+0

ありがとうございます。 'logging.basicConfig()'によってのみ定義されたハンドラの 'relevant_handlers'を取得できますか?そうでなければ、 'relevant_handlers'をどのように定義できますか? – EOL

+0

更新いただきありがとうございます。 Logging HOWTOを読む必要があります。具体的な解決方法を実装する前に、多分もっと多くのことを読む必要があります。 – EOL

関連する問題