Python / 開発ノウハウ
目次
print() を卒業しよう
Python logging モジュール完全入門
ログは「後から読む人」のために書くもの。適切なロギングを身につければ、デバッグ時間は劇的に短くなります。
開発中、何気なく print() でデバッグしていませんか?小さなスクリプトなら問題ありませんが、本番環境や大規模なアプリでは途端に管理が難しくなります。Python 標準の logging モジュールを使えば、情報の重要度に応じた出力制御や、ファイル・コンソールへの同時書き出しが、コードを書き換えることなく実現できます。
ロギングの4大要素
Python のロギングシステムは、以下の4つのオブジェクトが連携して動く「ロギング・フロー」で構成されています。
Logger
アプリが呼び出す入り口。レベルのフィルタも担う
Handler
送り先を決定。コンソール・ファイル・メールなど複数設定可
Filter
出力するレコードをより細かく制御する
Formatter
日時・レベル名・メッセージなど見た目を整える
5段階のログレベル
数値が大きいほど重要度が高くなります。デフォルトの出力しきい値は WARNING(30) です。
| レベル | 数値 | 用途 |
|---|---|---|
| DEBUG | 10 | 診断情報の詳細(開発用) |
| INFO | 20 | 期待通りの動作をしているかの確認 |
| WARNING | 30 | 予期せぬ事態の予兆(デフォルト) |
| ERROR | 40 | 重大な問題で一部機能が実行不能 |
| CRITICAL | 50 | プログラム自体が続行不能な致命的エラー |
実践コード:明示的なハンドラ設定
最も推奨される構成です。ロガー・ハンドラ・フォーマッタを分けて定義することで、後から柔軟に変更できます。
import logging # 1. ロガーの生成 logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) # 最低ログレベルを設定 # 2. ハンドラの作成(コンソール出力用) console_handler = logging.StreamHandler() console_handler.setLevel(logging.INFO) # INFO以上を出す # 3. フォーマッタの作成 formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) console_handler.setFormatter(formatter) # 4. ロガーにハンドラを登録 logger.addHandler(console_handler) # 実行例 logger.debug("これは表示されません(HandlerがINFO以上のため)") logger.info("サーバーを起動します") logger.warning("メモリ使用量が増加しています") logger.error("データベース接続に失敗しました")
なぜ print() ではなく logging なのか
一括切り替え
setLevel(ERROR) 一行でデバッグ出力を全消し。デプロイ時に手作業で print を消す必要がない。出力先の柔軟性
コンソールとファイルへの同時書き出しも、ハンドラを追加するだけ。コード本体は無変更。
付随情報の自動取得
どのファイルの何行目でエラーが起きたかを、フォーマッタが自動で記録してくれる。
ライブラリとの統合
Requests・Django など多くのライブラリも logging を使用。自作コードと一括管理が可能。
運用のコツ:__name__ の活用
推奨:
logging.getLogger(__name__) と書くことで、ロガー名にモジュール名(ファイル名)が自動的に付与されます。複数ファイルからログが出力される大規模アプリでも「どのファイルから出力されたか」がログ上で一目瞭然になります。
まとめ:いつ basicConfig を使うか
小規模なスクリプトであれば logging.basicConfig() でも十分です。しかしアプリが成長するにつれ、ハンドラを明示的に分けた構成のほうがメンテナンス性が格段に高まります。
注意:
basicConfig() はプログラム起動時に一度だけ有効です。すでにハンドラが設定されている場合は何も変更されません。チームや本番環境での利用は、明示的なハンドラ設定を強くお勧めします。
プログラミング情報サイト「In-Output」" width="1280" height="905" >