Day 27:ログで「あとから原因を追えるコード」にする
Day 27では、Python標準ライブラリの logging を使って、 DEBUG / INFO / WARNING / ERROR / ログファイル というキーワードを軸に、 「あとから原因を追えるコード」を書く感覚を身につけていきます。
ログとは何か:コードの「足跡」を残すもの
printとの違いをイメージする
プログラムの動きを確認するとき、多くの方が最初に使うのは print だと思います。
print("処理を開始します")
print("ユーザーID:", user_id)
print("処理が完了しました")
Pythonprint は手軽ですが、次のような問題があります。
- どこで何が出力されているか管理しづらい
- 本番環境では「画面に出るだけ」で、あとから追いづらい
- 重要度(ただの情報なのか、エラーなのか)が区別されない
そこで登場するのが ログ です。
- ログは「プログラムの動きを記録する仕組み」
- 重要度(レベル)を付けて記録できる
- ファイルに書き出して、あとから分析できる
という特徴があります。
loggingモジュールの基本を押さえる
最初の一歩:基本的なログ出力
Pythonには、ログを扱うための標準モジュール logging が用意されています。
import logging
# ログの基本設定を行います。
logging.basicConfig(level=logging.INFO)
logging.debug("これはDEBUGレベルのログです")
logging.info("アプリケーションを開始します")
logging.warning("設定ファイルが見つかりません。デフォルト設定を使用します")
logging.error("データベース接続に失敗しました")
Pythonここでのポイントは次の通りです。
logging.basicConfig(level=logging.INFO)- 「INFO以上のログを表示する」という設定です。
DEBUGはそれより下のレベルなので、この設定では表示されません。
logging.debug(...) / info(...) / warning(...) / error(...)- ログレベルごとにメソッドが用意されています。
実行すると、ターミナルに次のような出力が表示されます(環境によって多少異なります)。
INFO:root:アプリケーションを開始します
WARNING:root:設定ファイルが見つかりません。デフォルト設定を使用します
ERROR:root:データベース接続に失敗しました
ログレベルを理解する:DEBUG〜ERRORの役割
代表的なログレベル
logging には、代表的に次のログレベルがあります。
- DEBUG
- 開発中に細かい動きを追いたいときのログ
- 変数の中身・処理の途中経過など
- INFO
- 通常の動作を記録するログ
- アプリの起動・終了、重要な処理の開始・完了など
- WARNING
- 「今は動いているが、問題の兆候がある」ログ
- 設定ファイルが見つからない、古いAPIを使っているなど
- ERROR
- 「処理が失敗した」ログ
- 例外が発生した、外部サービスに接続できないなど
レベルによるフィルタリング
basicConfig の level で「どのレベル以上を出すか」を指定できます。
logging.basicConfig(level=logging.DEBUG) # DEBUG以上(全部)を出す
logging.basicConfig(level=logging.INFO) # INFO以上(INFO, WARNING, ERROR)を出す
logging.basicConfig(level=logging.WARNING) # WARNING以上(WARNING, ERROR)を出す
Python開発中は DEBUG を出し、本番環境では INFO 以上にする、といった使い分けがよく行われます。
ログファイルに書き出す:あとから読み返せるようにする
basicConfigでファイル出力を設定する
ログを画面に出すだけでなく、ファイルに保存することが重要です。 basicConfig に filename を指定すると、ログをファイルに書き出せます。
import logging
logging.basicConfig(
level=logging.DEBUG, # DEBUG以上のログを記録します
filename="app.log", # ログファイル名
filemode="a", # 追記モード ("w" にすると毎回上書き)
format="%(asctime)s [%(levelname)s] %(message)s" # ログの書式
)
logging.debug("デバッグ情報です")
logging.info("アプリケーションを開始します")
logging.warning("設定ファイルが見つかりません")
logging.error("致命的なエラーが発生しました")
Pythonこのコードを実行すると、カレントディレクトリに app.log が作成され、次のような内容が記録されます。
2026-08-30 09:39:00,123 [DEBUG] デバッグ情報です
2026-08-30 09:39:00,124 [INFO] アプリケーションを開始します
2026-08-30 09:39:00,125 [WARNING] 設定ファイルが見つかりません
2026-08-30 09:39:00,126 [ERROR] 致命的なエラーが発生しました
ここでのポイントは、
filenameで「どのファイルに書くか」を指定していることformatで「日時・レベル・メッセージ」を含む書式を指定していること- ログファイルをあとから開いて、「いつ・何が起きたか」を追えるようになること
です。
ロガーを使って「モジュールごと」にログを分ける
loggerオブジェクトを作る
少しだけ踏み込んで、logging.getLogger() を使った書き方も見ておきます。 これにより、「モジュールごと・機能ごと」にロガーを分けることができます。
import logging
# ログの基本設定
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s [%(name)s] [%(levelname)s] %(message)s"
)
# ロガーを取得します(名前を付けられます)。
logger = logging.getLogger("app")
logger.debug("デバッグ情報です")
logger.info("アプリケーションを開始します")
logger.warning("設定ファイルが見つかりません")
logger.error("致命的なエラーが発生しました")
Python出力例:
2026-08-30 09:39:00,123 [app] [DEBUG] デバッグ情報です
2026-08-30 09:39:00,124 [app] [INFO] アプリケーションを開始します
2026-08-30 09:39:00,125 [app] [WARNING] 設定ファイルが見つかりません
2026-08-30 09:39:00,126 [app] [ERROR] 致命的なエラーが発生しました
ここでのポイントは、
getLogger("app")で「名前付きロガー」を作っていること- ログ出力に
nameが含まれることで、「どのロガーから出たログか」が分かること
です。 大きなアプリでは、getLogger(__name__) を使って「モジュールごとにロガーを持つ」ことがよくあります。
ログと例外処理を組み合わせる
try/exceptでエラーをログに残す
ログは、例外が発生したときの情報を残すのにも役立ちます。
import logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s"
)
logger = logging.getLogger("app")
def divide(a, b):
"""割り算を行う関数です。"""
return a / b
def main():
logger.info("アプリケーションを開始します")
try:
result = divide(10, 0) # ゼロ除算で例外が発生します
logger.info("計算結果: %s", result)
except ZeroDivisionError as e:
logger.error("ゼロ除算が発生しました: %s", e)
logger.info("アプリケーションを終了します")
if __name__ == "__main__":
main()
Python出力例:
2026-08-30 09:39:00,123 [INFO] アプリケーションを開始します
2026-08-30 09:39:00,124 [ERROR] ゼロ除算が発生しました: division by zero
2026-08-30 09:39:00,125 [INFO] アプリケーションを終了します
ここでのポイントは、
- 例外が発生したときに
logger.error(...)で「何が起きたか」を記録していること - ログを見れば、「どのタイミングで、どんなエラーが起きたか」が分かること
です。
Day 27ミニテンプレート:ログ入門スクリプト
最後に、Day 27で学んだ内容をまとめて試せる「ログ入門スクリプト」のテンプレートを示します。
# day27_logging.py
# logging入門の練習用スクリプト
import logging
def setup_logger():
"""ロガーの基本設定を行う関数です。"""
logging.basicConfig(
level=logging.DEBUG, # DEBUG以上のログを記録します
filename="app.log", # ログファイル名
filemode="a", # 追記モード
format="%(asctime)s [%(name)s] [%(levelname)s] %(message)s"
)
return logging.getLogger("app")
def divide(a, b):
"""割り算を行う関数です。"""
return a / b
def main():
logger = setup_logger()
logger.info("アプリケーションを開始します")
logger.debug("10 / 2 の計算を行います")
result1 = divide(10, 2)
logger.info("10 / 2 の結果: %s", result1)
logger.debug("10 / 0 の計算を行います(エラーの例)")
try:
result2 = divide(10, 0)
logger.info("10 / 0 の結果: %s", result2)
except ZeroDivisionError as e:
logger.error("ゼロ除算が発生しました: %s", e)
logger.warning("このあとアプリケーションを終了します")
logger.info("アプリケーションを終了します")
if __name__ == "__main__":
main()
Pythonこのスクリプトを実行すると、
- ターミナルにはログが表示され
- 同時に
app.logにもログが記録されます
あとから app.log を開いて、「どんな処理が行われ、どこでエラーが起きたか」を確認できるようになります。
Day 27のまとめ
Day 27では、ログ入門として、
- ログ=「プログラムの足跡を残す仕組み」というイメージ
loggingモジュールで、DEBUG / INFO / WARNING / ERROR を使い分ける方法basicConfigでログレベル・書式・ファイル出力を設定する基本getLoggerで名前付きロガーを作り、モジュールごとにログを分ける考え方- 例外処理とログを組み合わせて、「エラーの原因をあとから追える」コードにする方法
をステップバイステップで体験していただきました。
ここまで来ると、「ただ動くコード」から一歩進んで、「あとから原因を追えるコード」を意識して書く感覚が少し育っているはずです。 この感覚は、今後の実践Python編で、規模の大きなアプリケーションや本番環境を扱うときに、トラブルを素早く発見・修正するための大きな武器になっていきます。
