python: loggingの出力値を文字列として取得したい
python の logging で出力した info とかを文字列として取得したい! という場合の方法についてのメモです。
下準備
- 単純な logger と stream handler (コンソールへの出力のハンドラ) を用意します。
- 詳しくは https://docs.python.org/ja/3/howto/logging.html#logging-advanced-tutorial など参考にしてみてください。
今回は logger / hander 両方に INFO level をつけましたので info よりも重要度が高いものだけ console に output されるようになっています。
from logging import getLogger, StreamHandler, Formatter handler = StreamHandler() handler.setLevel('INFO') logger = getLogger('nyk.510') logger.setLevel('INFO') logger.addHandler(handler)
https://docs.python.org/ja/3/howto/logging.html#loggers
組み込みの深刻度の中では DEBUG が一番低く、 CRITICAL が一番高くなります。たとえば、深刻度が INFO と設定されたロガーは INFO, WARNING, ERROR, CRITICAL のメッセージしか扱わず、 DEBUG メッセージは無視します。
なるほど。というわけで、一旦試してみましょう。
logger.warning('warn') logger.info('foo') logger.debug('debug') # debug はでないよ warn foo
確かに debug は出ないようになっていますね。
loggingの出力値を文字列として取得
さて本題の logging の出力をテキストとして取得する、です。これは要するに上記の例で言うと warn / foo / debug みたいな文字列を取得したい、ということです。 結論をいうと StringIO を stream にもつような handler を作成して logger に付与すればOKです。 テキストとして取得するっていうのはだいたい log をどこかに保存したいとかいう気持ちがあると思いますので、ちょっとおしゃれな formatter にして時間等も取得できるようにしています。
log_capture_io = io.StringIO() stream_handler = StreamHandler(stream=log_capture_io) # オシャに formatting formatter = Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') stream_handler.setFormatter(formatter) stream_handler.setLevel('INFO') logger.addHandler(stream_handler)
この状態で logger に先と同じように log を記録します。
logger.warning('warn') logger.info('foo') logger.debug('debug') # debug は console にでないよ
log の取得
作成した StreamIO から getvalue
すればOKです。
- 通常のコンソールアウトプットは単に文字列だったが,
formatter
をリッチにしているので取得される文字列には何時 log が記録されたかなどの情報も入っている - コンソールの方も普通の
StreamHandler
に formatter を設定すれば時間も表示できる.
s = log_capture_io.getvalue() s.splitlines() ['2020-08-01 07:59:41,132 - nyk.510 - WARNING - warn', '2020-08-01 07:59:41,135 - nyk.510 - INFO - foo']
後片付け
ずっと handler が付いていると記録され続けるので、いらなくなったら消しましょう
- io の close
- handler のひも付けを logger から削除
removeHandler
# 終わったら消しましょう log_capture_io.close() logger.removeHandler(stream_handler) log_capture_io.closed # True
close してしまうと value はもう取れませんので注意
log_capture_io.getvalue() --------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-10-b5f4bf9c6e8d> in <module> ----> 1 log_capture_io.getvalue() ValueError: I/O operation on closed file
上記コードは gist にもありますので参考にしてください ;). Logging Recording · GitHub