PythonのLoggingモジュールは、アプリケーションのログイベントやメッセージを保存する便利な方法として機能する、柔軟なイベント駆動型ログシステムを実装するために使用されます。
PythonのログモジュールのLoggerについて
Logger オブジェクトは、このモジュールのオブジェクトで、必要なすべてのロギングを行うために操作することができます。
Loggerオブジェクトをインスタンス化するには、常に次のように指定する必要があります。
log_object = logging.getLogger(name)
同じ名前で getLogger(name)
を複数回呼び出すと、常に同じオブジェクトへの参照が得られます。
コンソールへのメッセージの書き込み
イベントを報告する必要があるときは、ロガーオブジェクトの内容を出力して、メインで動作しているプログラムに状態の変化を通知します。
これを実現するために、LEVEL
と呼ばれる、出力するメッセージの重要度の区切りがあります。
これは対応するログファイルまたはコンソールに書き込むために使用されます。
デフォルトのレベルは WARNING
で、このレベル以上のイベントのみが追跡されます (つまり、デフォルトでは WARNING
、 ERROR
、 CRITICAL
が追跡されます)。
これにより、プログラマは選択した重要度に基づいて、これらのステータス・メッセージをどのように表示するかを制御することができます。
フォーマット logging.info(message)
はコンソールやファイルにメッセージを表示します。
具体的には、以下の様なコードになります。
import logging
logging.warning('Warning message')
logging.info('Works as expected')
以下の様に出力されます。
WARNING:root:Warning message
ファイルにログ結果を出力する方法
logging.basicConfig()
を使って、ロギングファイルハンドラを作成します。
以下は、logging.basicConfig(filename, level)を実行します。
import logging
logging.basicConfig(filename='sample.log' , level =logging.DEBUG)
logging.debug('Debug message')
logging.info('info message')
logging.warning('Warning message')
結果は以下の通りです。
root@Ubuntu # cat sample.log
DEBUG:root:Debug message
INFO:root:info message
WARNING:root:Warning message
1つ注意なのが、basicConfig()
の呼び出しは、debug()
や info()
などの呼び出しの前に行う必要があります。
basicConfig()
関数にはもう一つパラメータ filemode
があり、これはログファイルのモードを指定するものです。
以下の例では、sample.log
を書き込み専用にします。
つまり、このファイルに書き込まれたメッセージは、以前のファイルの内容を上書きします。
logging.basicConfig(filename='sample.log' , filemode ='w' , level =logging.DEBUG)
メッセージのフォーマットを変更する方法
デフォルトでは、出力メッセージには、ノードの名前とメッセージのレベルを含むメッセージヘッダがあります。
表示されるメッセージの形式を変更するには、適切な形式を指定する必要があります。
import logging
logging.basicConfig(format ='%(levelname)s:%(message)s' , level =logging.DEBUG)
logging.debug('sample message')
結果は以下の通りです。
DEBUG:sample message
メッセージに日付と時刻を表示する
メッセージ中の時刻を表すために、 %(asctime)s
フォーマット指定子を追加します。
import logging
logging.basicConfig(format ='%(asctime)s %(message)s' , datefmt ='%m/%d/%Y %I:%M:%S %p')
logging.warning('Sample message')
結果は以下の通り。
12/26/2019 12:50:38 PM Sample message
Loggerのオブジェクト名を変更する方法
ログメッセージは、デフォルトでは、最初の部分にレベルと使用されるロガーオブジェクトの名前が含まれています。
通常、引数 name
を指定しない場合、デフォルトはルートノードの名前である ROOT
となります。
それ以外の場合は、Pythonのパッケージの名前空間におけるモジュールの名前である __name__
変数を使用するのがよい方法です。
import logging
logger = logging.getLogger(__name__)
setLevelメソッドでメッセージのレベルを変更する
Logger オブジェクトは、メッセージが表示される閾値レベルを変更する方法を提供してくれます。
setLevel(level)
メソッドはロガーオブジェクトのレベルを設定するために使用されます。
以下の例では、logger.setLevel(level)
でロガーオブジェクトのレベルを設定します。
import logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logger.debug('Debug message')
結果は以下の通りです。
No handlers could be found for logger "__main__"
ロギングハンドラについて
ロギングハンドラは、ログ/コンソールに書き込む作業を行うコンポーネントです。
logger オブジェクトは、メッセージの内容を表示するためにロギングハンドラを呼び出します。
ハンドラは、ロガーの場合のように直接インスタンス化されることはありません。
ハンドラには様々な種類があり、それぞれがインスタンス化のためのメソッドを持っています。
ハンドラの種類
loggingモジュールには様々なHandlerがありますが、ここでは主に最もよく使われる3つのHandlerを取り上げます。
- ストリームハンドラー
- ファイルハンドラー
- NullHandler
StreamHandler
StreamHandler は、ログの出力を stdout
、 stderr
などのストリームや、パイプ、FIFO などの write()
と flush()
メソッドをサポートする任意のファイルライクオブジェクトに送るために使用されます。
StreamHandler() ` を使って StreamHandler オブジェクトを初期化し、Logger オブジェクトからコンソールにメッセージを表示することができます。
先ほどのコードは、 StreamHandler()
と handler.setLevel()
を呼び出すことで完成します。
import logging
logger = logging.getLogger(name='hi')
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
logger.addHandler(handler)
logger.debug('sample message')
結果は以下の通りです。
sample message
FileHandler
ファイルへのロギングには、FileHandlerオブジェクトを使用します。
これも StreamHandler オブジェクトと似ていますが、ここではファイルディスクリプタが参照され、ファイルへのロギングが行われます。
上記のスニペットは、ログハンドラのインスタンスを作成する際に変更することができます。
タイプをFileHandlerに変更することで、メッセージをファイルにロギングすることができます。
handler_name =logging.FileHandler(filename='sample.log' , mode ='a')
NullHandler
このハンドラは基本的に何も書き込まない(出力を /dev/null
にパイプするのと同じ)ので、ライブラリ開発者にとって便利な no-op ハンドラとして考えられています。