Pythonのデバッグでprint()を使うのはやめよう
loggingを使いましょう。という話が書籍『退屈なことはPythonにやらせよう』に書いてあったので最小限の使い方をまとめておく。
サンプルコード
loggingを使ってデバッグ情報(forループ中の変数の履歴とか)を出すサンプル:
import logging
logging.basicConfig(level=logging.DEBUG, format='%(levelname)s: %(message)s')
# logging.disable(logging.CRITICAL)
logging.debug('program begins.')
sum = 0
logging.debug('sum = {}'.format(sum))
# sum 1 through 100
for i in range(1,101):
sum += i
logging.debug('sum = {}, i = {}'.format(sum, i))
print('SUM_1^100 = {}'.format(sum))
logging.debug('program ends.')
出力結果:
DEBUG: program begins.
DEBUG: sum = 0
DEBUG: sum = 1, i = 1
DEBUG: sum = 3, i = 2
DEBUG: sum = 6, i = 3
# 中略
DEBUG: sum = 5050, i = 100
SUM_1^100 = 5050
DEBUG: program ends.
使い方の概要
import logging
loggingモジュールのインポート。
logging.basicConfig(level=logging.DEBUG, format='%(levelname)s: %(message)s')
loggingの基本設定。
levelは、実際にログに出力する閾値レベルを示す(指定した閾値よりも重要度が高いレベルしか出力しない)。logging.DEBUGは最低レベルらしいので、これを指定することで全てのlogging情報が出力される。
未指定の場合はlogging.WARNING相当になるようだ。
formatは、ログ出力時の形式を文字列で指定する。
%(levelname)s を記述すると、レベル名称(DEBUG, WARNINGなど)が入る。
%(message)s を記述すると、後ほどログ出力関数に渡した文字列の内容が入る。
ほかに %(asctime)s も指定できて、ログイベント発生時の日付・時刻が入る。
未指定の場合は 'DEBUG:root:デバッグメッセージ' みたいなデフォルトの出力フォーマットになる。
logging.debug('program begins.')
logging.debug('sum = {}'.format(sum))
ロギング出力指定(DEBUGレベル)。
引数に渡した文字列が、ログの %(message)s に入ることになる。
同じような使い方ができるものとしてlogging.info()とかlogging.warning()とかlogging.critical()とかあり、それぞれログとしての情報レベルが異なる。
変数の値をログに出力したい場合は、2行目のように変数値を含む文字列を渡す。
最小労力での使い方
import logging
spam = 42
logging.warning('value of spam: {}'.format(spam))
出力:
WARNING:root:value of spam: 42
デバッグ目的なのにWARNINGレベルで指定するのは嫌だ、とかデフォルトのフォーマットは嫌だ、という潔癖症の方はちゃんとlogging.basicConfig()を使って閾値とフォーマットを指定しましょう。
なぜprint()じゃダメでlogging.debug()がいいのか?
print()を使った場合、デバッグが不要になった(プログラムが完成した)際にはデバッグ出力のためのprint()を全て削除しなくてはならない。このとき、本来は必要な(完成プログラムにおいても出力したい)残すべきprint()も間違って削除してしまう恐れがあるし、たくさん記述したデバッグ用のprint()を全部削除していくのは大変。
logging.debug()を使った場合、ログ出力が不要になれば、プログラムの最初の方に下記の1行を追記すればすべてのログ出力を無効にできる(冒頭のサンプルコードではコメントアウトしてある):
logging.disable(logging.CRITICAL)
実際にはCRITICALレベル以下のログ出力を無効化を意味する記述だが、CRITICALは最高レベルなので実質的に「すべてのログ出力を無効化」に相当する。
その他
ログ情報をファイルに書き出したり、日付・時刻情報の書式を変えられたり、色々できるようですが細かいところはドキュメントを参照。
参考文献
『退屈なことはPythonにやらせよう』 10.4章
Pythonドキュメント Logging HOWTO
その他
1から100までの和はfor使わずにもうちょっとスマートにやりましょう(サンプルなのでご容認を)