私はPythonのloggingモジュールを使っていくつかのデバッグ文字列をファイルに記録します。それに加えて、このモジュールを使って文字列も標準出力に出力したいと思います。どうやってこれをするの?私の文字列をファイルに記録するために、私は以下のコードを使います:
import logging
import logging.handlers
logger = logging.getLogger("")
logger.setLevel(logging.DEBUG)
handler = logging.handlers.RotatingFileHandler(
LOGFILE, maxBytes=(1048576*5), backupCount=7
)
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)
その後、次のようなロガー関数を呼び出します。
logger.debug("I am written to the file")
ここで助けてくれてありがとう!
ルートロガーのハンドルを取得してStreamHandler
を追加するだけです。 StreamHandler
はstderrに書き込みます。本当にstderrよりもstdoutが必要かどうかはわかりませんが、これは私がPythonロガーをセットアップするときに使用するものであり、FileHandler
も追加します。それから私のすべてのログは両方の場所に行きます(それはあなたが望むように聞こえるものです)。
import logging
logging.getLogger().addHandler(logging.StreamHandler())
stdout
ではなくstderr
に出力したい場合は、それをStreamHandler
コンストラクターに指定するだけです。
import sys
# ...
logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))
Formatter
を追加して、すべてのログ行に共通のヘッダーを付けることもできます。
すなわち:
import logging
logFormatter = logging.Formatter("%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s] %(message)s")
rootLogger = logging.getLogger()
fileHandler = logging.FileHandler("{0}/{1}.log".format(logPath, fileName))
fileHandler.setFormatter(logFormatter)
rootLogger.addHandler(fileHandler)
consoleHandler = logging.StreamHandler()
consoleHandler.setFormatter(logFormatter)
rootLogger.addHandler(consoleHandler)
以下の形式で印刷します。
2012-12-05 16:58:26,618 [MainThread ] [INFO ] my message
logging.basicConfig()
はPython 3.3からキーワード引数handlers
を取ることができます。これはロギング設定を非常に単純化します。
handlers
- 指定された場合、これはルートロガーに追加するために既に作成されたハンドラのイテラブルであるべきです。まだフォーマッタセットを持っていないハンドラには、この関数で作成されたデフォルトのフォーマッタが割り当てられます。
したがって、受け入れられた答えからのかなり長くて冗長な例のコードはまさにこれになります:
import logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s] %(message)s",
handlers=[
logging.FileHandler("{0}/{1}.log".format(logPath, fileName)),
logging.StreamHandler()
])
(または、元の質問の要件に応じてimport sys
+ StreamHandler(sys.stdout)
で)
ロガーを取得するには、
logger = logging.getLogger()
スクリプトの後半で、便利なロギングメッセージを出力するためにlogger.info()
を使用してください。
引数なしでStreamHandlerを追加すると、標準出力ではなく標準エラー出力になります。他のプロセスが標準出力ダンプに依存している場合(つまりNRPEプラグインを作成するとき)、明示的に標準出力を指定するようにしてください。そうしないと予期しない問題が発生する可能性があります。
質問からの想定値とLOGFILEを再利用する簡単な例を示します。
import logging
from logging.handlers import RotatingFileHandler
from logging import handlers
import sys
log = logging.getLogger('')
log.setLevel(logging.DEBUG)
format = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
ch = logging.StreamHandler(sys.stdout)
ch.setFormatter(format)
log.addHandler(ch)
fh = handlers.RotatingFileHandler(LOGFILE, maxBytes=(1048576*5), backupCount=7)
fh.setFormatter(format)
log.addHandler(fh)
他のハンドラの設定やメッセージのロギングの前に、引数としてstream=sys.stdout
を指定してbasicConfig
を実行するか、または標準出力にメッセージをプッシュするStreamHandler
を手動でルートロガー(または、その他の任意のロガー)に追加します。
Waterboyのコードを複数のPythonパッケージで何度も使用した後、私はついにそれを小さなスタンドアロンのPythonパッケージにキャストしました。
https://github.com/acschaefer/duallog
コードはよく文書化されていて使いやすいです。単に.py
ファイルをダウンロードしてあなたのプロジェクトに含めるか、pip install duallog
を通してパッケージ全体をインストールしてください。