Pythonのloggingモジュール入門:print関数を使わずにログを出力すべき理由と基本設定

開発中のデバッグや、本番環境での動作確認において、「プログラムがどこまで進んだか」「変数の値はどうなっているか」を確認するために print() 関数を使用することはよくあります。

しかし、本格的なアプリケーション開発においては、print() ではなく標準ライブラリの logging モジュールを使用することが強く推奨されます。

この記事では、logging モジュールの基本的な使い方、ログレベルの概念、そして出力フォーマットの設定方法について解説します。

目次

なぜ print() ではなく logging なのか

print() 関数と比較して、logging モジュールには以下のような利点があります。

  1. ログレベルによる制御: 重要度(エラー、警告、情報など)に応じて、出力するログを簡単にフィルタリングできます(例:本番環境ではデバッグ情報を出さない)。
  2. 出力先の変更: 標準出力(コンソール)だけでなく、ファイルへの保存やメール送信など、出力先(ハンドラ)を柔軟に変更できます。
  3. フォーマットの統一: 日時、ファイル名、行番号などのメタ情報を自動的に付与し、ログの形式を統一できます。

ログレベルの理解

logging モジュールには、重要度の低い順に5つのログレベルが定義されています。設定したレベル以上のログが出力されます。

レベル定数名数値用途
DEBUGlogging.DEBUG10開発中の詳細な情報。動作確認用。
INFOlogging.INFO20正常な動作の報告。処理の開始・終了など。
WARNINGlogging.WARNING30想定外だが実行可能な問題。警告。
ERRORlogging.ERROR40重大な問題により機能を実行できない場合。
CRITICALlogging.CRITICAL50プログラム自体が停止するような致命的なエラー。

デフォルトの設定では WARNING 以上 のログのみが出力され、INFO や DEBUG は無視されます。

基本的な実装例

それでは、実際に logging モジュールを使ってログを出力するコードを作成します。

ここでは、basicConfig を使って全体のログ設定を行い、getLogger(__name__) でモジュール専用のロガーを取得するという、最も標準的なパターンを紹介します。

import logging

# 1. ログの基本設定
# level: 出力する最低レベルを指定 (ここではINFO以上)
# format: ログの出力形式を指定 (日時 - ロガー名 - レベル - メッセージ)
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)

# 2. ロガーの取得
# __name__ を渡すことで、どのモジュールからのログかを識別しやすくする
logger = logging.getLogger(__name__)

def perform_task(task_id):
    # 情報レベルのログ (出力される)
    logger.info(f"タスク {task_id} の処理を開始します。")
    
    # デバッグレベルのログ (INFO設定なので出力されない)
    logger.debug(f"タスク {task_id} の詳細デバッグ情報...")

    if task_id < 0:
        # エラーレベルのログ (出力される)
        logger.error("タスクIDが不正です。処理を中断します。")
        return

    # 警告レベルのログ (出力される)
    if task_id > 1000:
        logger.warning("タスクIDが大きすぎます。処理に時間がかかる可能性があります。")

    logger.info(f"タスク {task_id} が完了しました。")

# --- 実行 ---
print("--- 処理実行 ---")
perform_task(10)
print("\n--- エラー発生ケース ---")
perform_task(-1)

実行結果:

--- 処理実行 ---
2025-11-29 10:30:05,123 - __main__ - INFO - タスク 10 の処理を開始します。
2025-11-29 10:30:05,123 - __main__ - INFO - タスク 10 が完了しました。

--- エラー発生ケース ---
2025-11-29 10:30:05,124 - __main__ - INFO - タスク -1 の処理を開始します。
2025-11-29 10:30:05,124 - __main__ - ERROR - タスクIDが不正です。処理を中断します。

コードの解説

  1. logging.basicConfig(…):ログシステムの初期設定を行います。level=logging.INFO としたため、logger.debug() の内容は出力されていません。
  2. format=”…”:ログの出力形式を指定しています。
    • %(asctime)s: 日時
    • %(name)s: ロガー名(ここでは __name__ なので __main__
    • %(levelname)s: ログレベル名(INFO, ERRORなど)
    • %(message)s: ログメッセージ本文
  3. logging.getLogger(__name__):ロガーオブジェクトを作成します。引数にモジュール名(__name__)を渡すのが慣例です。これにより、ログがどのファイルから出力されたかが明確になります。

ログをファイルに出力する(ハンドラ)

画面に表示するのではなく、ファイルに保存したい場合は、basicConfigfilename 引数を追加するだけで実現できます。

logging.basicConfig(
    filename="app.log",  # 出力するファイル名
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s"
)

これを実行すると、コンソールには何も表示されなくなり、代わりに実行ディレクトリに app.log というファイルが作成され、そこにログが追記されます。

まとめ

  • ログ出力には print() ではなく logging モジュールを使用します。
  • 5つのログレベル(DEBUG, INFO, WARNING, ERROR, CRITICAL)を使い分けます。
  • logging.basicConfig() でレベルやフォーマットを一括設定できます。
  • logger = logging.getLogger(__name__) でロガーインスタンスを作成して使用します。
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次