ログは、コードの実行中に発生したイベントを記録し、将来的にデバッグのために使用することができます。アプリケーションの流れをよりよく把握することができ、コードの実行中に発生したエラーの原因を突き止めることができるため、アプリケーションの保守性を高めることができます。
Pythonでは、基本的なロギング機能のほとんどがPythonの標準ライブラリで提供されています。したがって、余分な設定をすることなく、簡単にアプリケーションにロギングを追加することができます。標準のロギングモジュールによって、開発者はステータスメッセージをファイルや他の出力ストリームに書き込むことができます。
ロギングモジュール
logging` モジュールは Python 環境でデフォルトで利用可能で、”root” という名前のデフォルトのロガーを提供します。このモジュールは、ロギング機能を実装する関数やクラスを定義しています。
標準ライブラリによって提供されるロギングAPIは、サードパーティモジュールのメッセージとの統合と同様に、アプリケーションログにあなた自身のメッセージを含めることを可能にします。また、ログメッセージにソース、タイムスタンプ、重要度などのメタデータを注釈する仕組みも提供し、ログ解析に役立てることができる。
ログの種類(ログレベル)
各ログメッセージは、ログに記録されたイベントの重要度を示す整数である重要度レベルに関連付けられています。logging モジュールには、各ログレベルのためのヘルパー関数があります – これらは、ログレベルに従って命名されます。以下は、ログレベルのリストと推奨される使用方法です。
- デバッグ (
logger.debug
): 非常に詳細な出力を提供します。問題を診断するために使用します。 - Info (
logger.info
): 正常に実行された場合の情報を提供します。期待通りに動作しているかどうかを確認します。 - 警告 (
logger.warn
またはlogger.warning
): 警告 (logger.warn
orlogger.warning
): 将来発生する可能性のある問題や回復可能な障害に関する警告を発します。 - エラー (
logger.error
): * エラー (logger.error
): ソフトウェアが期待通りに実行されないなど、ソフトウェアに問題があることを示しま す。 - クリティカル(
logger.critical
)。プログラムの実行を停止させる可能性のある重大なエラーを示します。
デフォルトでは、ルートロガーは、警告レベル以上のすべてのメッセージを報告するように設定され ています – このレベル以下のメッセージはフィルターされます。しかし、フィルタリングをより選択的に、あるいはより少なくするために、モジュールを明示的に設定することが可能です。
Pythonスクリプトにログを追加するには、単に import logging
を使ってモジュールをインポートします。インポートに成功すると、スクリプトは logging.*
メソッド、例えば logging.debug()
を使ってメッセージを記録することができます。
ここでは、loggingモジュールが動作している簡単な例を見ることができます。
import logging
logging.warning("Caution: This is the root logger!")
出力
出力: “`
WARNING:root:Caution: This is the root logger!
### ロガーオブジェクト
logging` モジュールは、ユーザーが複数の logger オブジェクトを作成することを可能にします。例えば、メインの Python アプリは `root` ロガーを使用し、このアプリから使用されるサードパーティライブラリは、独自の設定を持つ独自のロガーオブジェクトを使用することができます。
デフォルトの `root` logger の関数を使用しながら、例えば、 `logging.debug()` のように直接関数を呼び出すことができます。Logger` クラスのオブジェクトを作成することで、独自のロガーを設定することも可能で、アプリケーションが複数のモジュールを持つ場合に便利です。
それでは、 `logging` モジュールのクラスと関数のいくつかを見てみましょう。基本的なクラスとその機能は以下のとおりです。
* Loggers - アプリが使用するインターフェイスを公開します。このクラスのオブジェクトは、アプリケーション内の関数を呼び出すために直接使用されます。
* ハンドラ - ログメッセージを、標準出力コンソール、ファイル、HTTP経由、あるいは電子メール(SMTP経由)など、ソフトウェア内の適切な場所に送信します。
* フィルタ - 表示するログレコードの選択に対するきめ細かい制御を提供します。
* フォーマッタ - ログレコードの最終的なレイアウトを指定し、出力が含まなければならない属性を指定する。
これらのうち、最も頻繁に使用されるのは `Logger` クラスのオブジェクトです。
新しいロガーを作成するには、 `logging.getLogger()` メソッドを使用します。次のスクリプトでは、`root` ロガーとカスタムロガー `my_logger` を使ってエラーを記録しています。
import logging
my_logger = logging.getLogger(“My Logger”)
logging.error(“Error: Root Log”)
my_logger.error(“Error: My Logger log”)
出力
ERROR:root:Error: Root Log
ERROR:My Logger:Error: My Logger log
それぞれのログメッセージは、ソース(ログが記録されたロガーオブジェクト)を示すだけでなく、そのロガーオブジェクトの設定に基づいたメッセージを表示します。
次のセクションでは、ロガーオブジェクトの様々な設定オプションを見ていきます。
### ファイルへのログ記録と標準出力の比較
デフォルトでは、ロガーオブジェクトはログを標準出力に出力します。basicConfig()` メソッドを使うと、このパラメータや他のパラメータを変更することができます。以下は `basicConfig` メソッドのパラメータのリストです。
* level: ロガーに深刻度レベルを設定します。この重要度レベル以下のメッセージはログに記録されません。
* filename: ログが書き込まれるファイルの名前です。
* filemode: filemode: 指定されたファイルがある場合、それを開くモード。
* format: ログメッセージのフォーマットを指定します。ログメッセージの形式を指定します。これは `LogRecord` 属性を持つ文字列です。
LogRecord` オブジェクトは、行番号、時間、ロガーの名前など、ログに記録されるイベントの情報を含んでいます。LogRecordオブジェクトについて説明することは、この記事の範囲外ですが、より詳しい情報はここにあります。
以下は、ログイベントをファイルに記録するための手順の概要です。
1. 1. logging モジュールをインポートする。
2. 2. `basicConfig` メソッドを使用してロガーを設定する。
3. logger オブジェクトを作成する。
4. loggerの閾値の設定
5. ロギングメソッドを使用する。
例題で説明すると分かりやすいでしょう。
Filename: test_logger.py
import logging
Create a logger object
logger = logging.getLogger()
Configure logger
logging.basicConfig(filename=”test.log”, format=’%(filename)s: %(message)s’, filemode=’w’)
Setting threshold level
logger.setLevel(logging.DEBUG)
Use the logging methods
logger.debug(“This is a debug message”)
logger.info(“For your info”)
logger.warning(“This is a warning message”)
logger.error(“This is an error message”)
logger.critical(“This is a critical message”)
上記のスクリプトは、ファイル "test.log "を作成します。このファイルには、次のようなロギング情報が含まれます。
test_logger.py: This is a debug message
test_logger.py: For your info
test_logger.py: This is a warning message
test_logger.py: This is an error message
test_logger.py: This is a critical message
### ログメッセージの日付/時間
イベントが発生した日時を表示するには、`basicConfig()` 関数のフォーマット文字列で `%(asctime)s` を使用します。例えば
import logging
logging.basicConfig(format=’%(asctime)s %(message)s’)
logging.warning(‘is the time the Admin logged out.’)
出力します。
2018-12-17 10:52:15,463 is the time the Admin logged out.
日付/時刻の表示方法を変更したい場合は、`basicConfig` メソッドの `datefmt` パラメータを使用して設定することができる。
### ロギング変数
実際のアプリケーションでは、アプリケーションで起こる動的な変化に応じてログを出力する必要があります。上の例で見たように、ロギングメソッドは引数として文字列を受け取ります。さらに、変数を含め、プレースホルダーで文字列をフォーマットして、ログメソッドに渡すことができます。実行時には、変数の値がログメッセージに出力されます。
以下は、文字列の書式設定を使った例です。
import logging
status = “connection unavailable”
logging.error(“System reported: %s”, status)
出力されます。
ERROR:root:System reported: connection unavailable
Python 3.6から、f-stringは文字列フォーマット指定子の代わりとして使うことができ、それによって複数のパラメータがあるときにコードを簡単に読むことができるように維持します。f-stringsを使うと、メッセージの一部として任意のPython式を指定でき、これらは実行時に評価され、その結果がログメッセージに埋め込まれます。
上記の例は、f-stringを使用して次のように書き直すことができます。
import logging
status = “connection unavailable”
logging.error(f’System reported: {status}’)
### スタックトレースのログ取得
アプリケーションのスタックトレースを取得することも logging モジュールでサポートされています。logging 関数を呼び出す際に `exc_info` パラメータを `True` に設定すると、例外情報を取得することができるようになります。この関数を使うことで、現在処理されている例外の情報を取得することができます。この情報は、現在のスレッドと現在のスタックフレームに固有のものです。
import logging
my_list = [1, 2]
try:
print(my_list[3]) # Index out of range
except Exception as e:
logging.error(“Caught Exception!”, exc_info=True)
出力する。
出力:```
ERROR:root:Caught Exception!
Traceback (most recent call last):
File "index.py", line 5, in <module
print(my_list[3]) # Index out of range
IndexError: list index out of range
例外が現在のスタックフレームで処理されない場合、次にその呼び出し元(すなわち呼び出し元のスタックフレーム)から情報を取得し、例外を処理するスタックフレームを見つけるまで続けます。スタックフレームは、直近に処理された例外の情報を持っています。
スタックに処理中の例外がない場合は, None
という値を持つタプルを返します.それ以外の場合は, type
(処理された例外の種類), value (例外パラメータ), traceback (例外が最初に発生したコールスタックをカプセル化したトレースバックオブジェクト) の値を返します.
結論
logging モジュールの設計は非常に実用的で、小さなプロジェクトに基本的なロギングを追加できる、 すぐに使えるロギング機能を提供します。それは、最も要求の厳しいアプリケーションのニーズをサポートするために、 logger オブジェクトとその豊富な設定オプションを使うことによって、簡単に拡張することができます。メッセージに加えて、logging モジュールは、例外とスタックトレースを記録するために使用することもできます。これで、Python でロギングを実装するための基本的なチュートリアルは終わりです。
</module