はじめに
簡単な使い捨てのコードならprint()
によるログでもいいんですが、Python標準のロギングも決して難しくないので、せっかくだから最初からこれを使いましょう、という話です。
ライブラリを作る人向けの情報
ライブラリを作る人は、getLogger()
だけ覚えてください。
引数は文字列ですが何でも良いです。とりあえず今回は__name__
を入れておきましょう。
import logging
logger = logging.getLogger(__name__)
logger.info('こんにちは!')
モジュールで使うなら、こんな感じ。
import logging
logger = logging.getLogger(__name__)
class Dog(object):
def __init__(self, name):
self.name = name
def bark(self):
logger.debug('%s is barking', self.name)
logger.info('%s: bow!', self.name)
ググっていると稀にgetLogger()
せずに、loggingモジュールに直接info()
等で出力するサンプルを見かけますが、その場合ルートロガーへの出力となってしまいます。
ロガーは階層構造になっており、ルートロガー(階層構造の最上位)に出力してしまうと、後々仕分けなどで面倒なことになってしまいます。
import logging
logging.info('さようなら~') # これは駄目
必ず名前付きロガーを生成してから、出力しましょう。
あと、ログ出力のときにformatを叩いているようなサンプルもありますが、ログを出力しないで済む場面(たとえば出力をINFO以上にしている場合のdebug()
など)でもformatが必ず実行されるため、無駄に遅くなるので注意しましょう。
logger.debug('{}'.format(name)) # NG
logger.debug('%s', name) # OK!
アプリケーションを作る人向けの情報
アプリケーションというか、実行プログラム本体の方ですね。
basicConfig()
だけ覚えてください。
import logging
from animals.dog import Dog
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
dog1 = Dog('pochi')
dog1.bark() # => 'INFO:animals.dog:pochi: bow!'
basicConfig()
を使って、出力するログのレベル、出力先、フォーマットなどを指定できます。
何もしなければ、WARNING以上を標準エラー出力に垂れ流すだけなので、最悪何もしなくても、そこそこ大丈夫です。
注意すべきなのは、basicConfig()
の呼び出しは、アプリケションの実行を通じて、最初の1回のみが有効なことです(Python3.8以降はforce
オプションが追加されたので、強制的に設定を上書き出来るようです)。
importして使うファイルの中でbasicConfig()
を呼び出してしまうと、アプリ側でログの設定変更が出来なくなってしまいますので、ライブラリの中でbasicConfig()
は使わないようにしてください。
ロガーは「階層構造」になっていると先に説明しましたが、アプリケーション全体はWARNING以上、animalsは開発中なのでDEBUG、でもDogクラスだけは開発が終わって安定しているのでINFOでログりたい、みたいな場合は以下のように設定できます。
logging.basicConfig(level=logging.WARNING)
logging.getLogger('animals').setLevel(DEBUG)
logging.getLogger('animals.dog').setLevel(INFO)
まとめ
-
getLogger()
だけ覚えてください。 - 設定を変えたくなったら
basicConfig()
を思い出してください。