プログラミング初心者がアーキテクトっぽく語る

見苦しい記事も多数あるとは思いますが訂正しつつブログと共に成長していければと思います

PythonでLogging(複数Pythonファイル対応)

「素人コードにこれをパパッと加えればたちまちお店の味に」というソフトウェア業界の「味の素」がloggingです。

以前、Javaで同じような記事を書きましたが、Pythonでもログ出力をprintからloggingにするだけで雰囲気がぐっと良くなります。

architecting.hateblo.jp

また積極的にログを残すことができるようになりコードの保守性も向上します。(本来、こっちが主目的)

でもコードを書き進めていくとPythonファイルの数が増えてきますよね。 ファイルが増えるたびにlogger設定を書くのは面倒くさい。

そこで今回はメインとなるPythonファイルでlogger設定を行い、他のPythonファイルでは同じloggerを使い回す方法をご紹介します。 これでPythonファイルがどれだけ増えても安心です。


方法1

必要なコード量が少ないです。

自分のコードだけでなく、利用しているライブラリのログも出力されます。 これが好ましいときもあれば嫌なときもあるでしょう。

嫌な場合は2番目の方法を試してください。

メインとなるPythonファイルに記述

from logging import basicConfig, StreamHandler, DEBUG

basicConfig(
    level=DEBUG,
    format='%(asctime)s %(name)s:%(lineno)s %(funcName)s [%(levelname)s]: %(message)s'
)

ログ出力したい各ファイルに記述

from logging import getLogger

logger = getLogger(__name__)
logger.debug('hello')

方法2

1番目に比べると少し長いですが大した差はありません。

個人的にはこちらの方がよく使います。

メインとなるPythonファイルに記述

from logging import getLogger, StreamHandler, DEBUG, Formatter

logger = getLogger("<パッケージ名>")
handler = StreamHandler()
handler.setLevel(DEBUG)
handler.setFormatter(Formatter('%(asctime)s %(name)s %(filename)s:%(lineno)s %(funcName)s [%(levelname)s]: %(message)s'))
logger.setLevel(DEBUG)
logger.addHandler(handler)
logger.propagate = False

getLoggerの引数はなんでもよいですが、私はパッケージ名にしてます。

logger.setLevelではロガーがハンドラーに送るログレベルを指定します。 handler.setLevelではハンドラが出力先(画面やファイル等)に送るログレベルを指定します。

ログ出力したい各ファイルに記述

from logging import getLogger

logger = getLogger("<パッケージ名>")
logger.debug('hello')

getLoggerの引数にはメインファイルのgetLoggerで指定したパッケージ名を記載してください。

なお、ファイルごとに振る舞いを変えたい場合(「このモジュールだけログレベルを上げたい」等)は以下の要領で子Loggerを取得して適当に設定変更してください。

logger = getLogger("<パッケージ名>").getChild(__name__)
logger.setLevel(INFO)
<その他loggerの設定>

Formatter

方法1、方法2ともにFormatは以下を参考に適当に変更しましょう。

docs.python.org