Python でログ(ロギング)を実装します。
プログラマにとって、ログはとても大事なものです。何か問題が発生したとき、ログが無いために原因を特定できないという経験をした人もたくさんいるのではないでしょうか。
また、Python に限った話ではありませんが、print() 関数をログの代わりに使っちゃダメといいますが、ベストプラクティスがあります。
自分だけのプログラムであればいいですが、仕事で使うプログラムであれば、必ずログはいれましょう。
Contents
バージョン
- Python 3.5.4
logging モジュール
はじめに Python のログについて、簡単に説明したいと思います。本当に簡単にしか説明しないので、詳しくは公式のドキュメントを参照してください。
ログレベル
レベル | 内容 |
---|---|
DEBUG | おもに問題を診断するときにのみ関心があるような、詳細な情報。 |
INFO | 想定された通りのことが起こったことの確認。 |
WARNING | 想定外のことが起こった、または問題が近く起こりそうであることの表示。 |
ERROR | より重大な問題により、ソフトウェアがある機能を実行できないこと。 |
CRITICAL | プログラム自体が実行を続けられないことを表す、重大なエラー。 |
上記のように、ログにはレベルがあります。下に行くほどレベルは高くなります。ログのレベルとは重要度や優先度の意味なので、レベルが高くなるということは、問題が深刻になるということです。
ログフォーマット
フォーマット | 内容 |
---|---|
%(asctime)s | 時刻。デフォルトは “2003-07-08 16:49:45,896″。 |
%(filename)s | ファイル名。 |
%(funcName)s | 関数名。 |
%(levelname)s | ログレベル。 |
%(lineno)d | 行番号。 |
%(message)s | ログメッセージ。 |
ログのフォーマットです。ログとして出力する情報は自分で好きに決めれますが、よく使う情報は、logging モジュールがあらかじめ用意しています。その中でも私がよく使うものを上記の表にまとめました。上記の表以外にも logging モジュールが用意しているものがありますので、気になる方はドキュメントを参照してください。
簡単なログ出力
それでは、さっそく実装に入っていきたいと思います。まず最初は、簡単なログ出力について実装したいと思います。
実装
import logging logging.basicConfig(filename='simple_logging.log', level=logging.DEBUG, format='%(asctime)s %(levelname)s %(filename)s %(lineno)d %(message)s') logging.debug('logging.debug.') logging.info('logging.info.') logging.warning('logging.warning.') logging.error('logging.error.') logging.critical('logging.critical.')
basicConfig() の引数 filename を指定すると、ログをファイルに出力します。しかし、コンソール上には何も出力してくれないので注意が必要です。
引数 level ではログを出力するレベルを決めます。上記では、DEBUG を指定しているので、全てのログを出力しますが、WARNING にすると、DEBUG と INFO は出力しません。
動作確認
$ python simple_logging.py $ cat simple_logging.log 2019-05-05 22:58:42,096 DEBUG simple_logging.py 5 logging.debug. 2019-05-05 22:58:42,096 INFO simple_logging.py 6 logging.info. 2019-05-05 22:58:42,096 WARNING simple_logging.py 7 logging.warning. 2019-05-05 22:58:42,096 ERROR simple_logging.py 8 logging.error. 2019-05-05 22:58:42,096 CRITICAL simple_logging.py 9 logging.critical.
実装したプログラムを実行すると、上記のようになりました。
少し複雑なログ出力(ファイルとコンソールに同時にログ出力)
先ほどのログ出力でも十分ですが、ログがファイルのみの出力なので、少しデバッグしずらいです。なので、今度はファイルとコンソール両方にログを出力したいと思います。
実装
import logging logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) # ファイルハンドラ fh = logging.FileHandler('advance_logging.log') fh.setLevel(logging.DEBUG) # コンソールハンドラ ch = logging.StreamHandler() ch.setLevel(logging.ERROR) # フォーマット formatter = logging.Formatter('%(asctime)s %(levelname)s %(filename)s %(lineno)d %(message)s') fh.setFormatter(formatter) ch.setFormatter(formatter) logger.addHandler(fh) logger.addHandler(ch) logger.debug('logging.debug.') logger.info('logging.info.') logger.warning('logging.warning.') logger.error('logging.error.') logger.critical('logging.critical.')
ファイル用のハンドラとコンソール用のハンドラを定義し、addHandler() でセットします。ハンドラ毎にログレベルを変えることができますので、上記では、ファイルは全てのログレベルを出力し、コンソールは ERROR 以上を出力するようにしています。(デバッグ目的ならコンソールも DEBUG が良いです。)
動作確認
$ python advance_logging.py 2019-05-06 21:45:33,822 ERROR advance_logging.py 23 logging.error. 2019-05-06 21:45:33,822 CRITICAL advance_logging.py 24 logging.critical. $ cat advance_logging.log 2019-05-06 21:45:33,820 DEBUG advance_logging.py 20 logging.debug. 2019-05-06 21:45:33,821 INFO advance_logging.py 21 logging.info. 2019-05-06 21:45:33,821 WARNING advance_logging.py 22 logging.warning. 2019-05-06 21:45:33,822 ERROR advance_logging.py 23 logging.error. 2019-05-06 21:45:33,822 CRITICAL advance_logging.py 24 logging.critical.
実装したプログラムを実行すると、上記のようになりました。
まとめ
Python でログ(ロギング)を実装しました。Python の logging モジュールはさらに、ロガー、ハンドラ、フィルタ、フォーマッタのモジュールに分かれ、機能が豊富で、様々なシーンで柔軟に利用できるようになっていますので、ぜひ一度ドキュメントをチェックしてみてください。