3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Python]logging.loggerラッパから呼び出し元のログを正しく出力する

Last updated at Posted at 2020-12-28

背景

  • logging.loggerを拡張していく中でLoggerオブジェクトをフィールドに持つようなLoggerWrapperオブジェクトを作りたくなることがあると思われる。
  • ただしその場合、LogRecordオブジェクトに含まれる呼び出し元の情報=スタック情報( pathname, lineno, func )が、LoggerWrapperのlogメソッドを参照してしまい、元々の呼び出し元の情報が出力されなくなってしまう。
  • そのため、以下の方法でスタック情報を正しく出力する必要がある。
  • 以下の方法は、参照するスタックの深さを変更するものである。

スタック情報の出力方法

Python 3.8以降: loggingのstacklevelを利用

Python3.8からloggingモジュールで今回のユースケースに対するサポートが入った。
利用方法としては以下の二種類が考えられる。

ログ出力のキーワード引数として渡す

logger.info(msg, stacklevel=2)

stacklevel というのが追加されたパラメータである。参照したい呼び出し元までの深さを設定する。

loggerオブジェクトのメソッドを使って参照する

stack_filename, stack_lineno, stack_function = logger.findCaller(True, 3)[0:3]
  • findCallerの第2引数に深さを渡す。
  • LoggerAdapterやLoggerFormatterの中でスタック情報をまとめたい場合はこちらを使うのが良さそう。

Python 3.7以前: 独自関数を定義

loggingパッケージでのサポートはないので、 inspect パッケージを利用して、スタック情報を取得する関数を定義する。

[2]が深さを表す
import inspect

def stack_info() -> dict:
    stack = inspect.stack()[2]
    return {
        'stack_filename': stack.filename, 
        'stack_lineno': stack.lineno,
        'stack_function': stack.function,
    }

利用例

logger.info(msg, extra=stack_info())

終わり

  • LoggerWrapperオブジェクトを利用する場合、今回のようにスタック情報を正しく出力するために仕込みが必要になる。
  • そのため、logging.LoggerAdapterなどを利用してやり切れないか検討した上でLoggerWrapperオブジェクトの導入を検討した方が良さそう。
3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?