nykergoto’s blog

機械学習とpythonをメインに

python: loggingの出力値を文字列として取得したい

python の logging で出力した info とかを文字列として取得したい! という場合の方法についてのメモです。

下準備

今回は 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