開発中に最低限これだけ押さえればOK、という典型的なlogging使い方まとめ。
※本番向けチューニング(QueueHandler・JSON構造化など)は割愛。
1️⃣ プロジェクトで最初に設定する「基本セットアップ」
# app/logging_setup.py
import logging
def setup_logging(level=logging.INFO):
fmt = "%(asctime)s [%(levelname)s] %(name)s - %(message)s"
logging.basicConfig(
level=level,
format=fmt,
datefmt="%Y-%m-%d %H:%M:%S",
)
# app/main.py
import logging
from app.logging_setup import setup_logging
setup_logging(logging.DEBUG) # 開発中はDEBUGで詳細表示
logger = logging.getLogger(__name__)
logger.debug("debug message")
logger.info("start process")
logger.warning("this is a warning")
logger.error("something went wrong")
✅ よくあるポイント
-
logging.basicConfig()は一度だけ呼ぶ。 - 各モジュールでは
logger = logging.getLogger(__name__)を書く。 - 文字列整形は
"x=%s", x形式にして遅延評価。
2️⃣ 例外ログ(これだけで十分)
try:
1 / 0
except Exception:
logger.exception("unexpected error") # ← 自動でstack trace付き
出力例:
2025-11-02 14:33:45 [ERROR] app.main - unexpected error
Traceback (most recent call last):
File "main.py", line 10, in <module>
1 / 0
ZeroDivisionError: division by zero
3️⃣ モジュールごとにロガーを分ける(慣例)
project/
├─ main.py
├─ service/
│ ├─ user.py
│ └─ payment.py
└─ logging_setup.py
# service/user.py
import logging
logger = logging.getLogger(__name__)
def create_user(email):
logger.info("Creating user: %s", email)
# main.py
from service.user import create_user
create_user("test@example.com")
出力:
2025-11-02 14:33:45 [INFO] service.user - Creating user: test@example.com
これでモジュールごとに「どこから出たログか」がすぐわかる。
4️⃣ ファイルにも同時出力したい(よくあるやつ)
import logging
from logging import FileHandler, StreamHandler, Formatter
def setup_logging():
fmt = Formatter("%(asctime)s [%(levelname)s] %(name)s - %(message)s")
console = StreamHandler()
console.setLevel(logging.INFO)
console.setFormatter(fmt)
file = FileHandler("app.log", encoding="utf-8")
file.setLevel(logging.DEBUG)
file.setFormatter(fmt)
root = logging.getLogger()
root.setLevel(logging.DEBUG)
root.addHandler(console)
root.addHandler(file)
出力例:
- 画面には INFO以上
- ファイルには DEBUG以上
5️⃣ extra でちょっとしたコンテキスト情報を載せる
logger.info("login success", extra={"user_id": 42})
フォーマットで %(user_id)s を指定しておくと自動で展開される:
logging.basicConfig(format="%(asctime)s [%(levelname)s] [user=%(user_id)s] %(message)s")
出力:
2025-11-02 14:33:45 [INFO] [user=42] login success
6️⃣ テスト中にログをキャプチャ(pytest)
def test_log(caplog):
caplog.set_level(logging.INFO)
logger.info("task done")
assert "task done" in caplog.text
7️⃣ noisyなライブラリのログを抑える(よくやる)
logging.getLogger("urllib3").setLevel(logging.WARNING)
logging.getLogger("botocore").setLevel(logging.ERROR)
8️⃣ 開発時にだけ DEBUG 出す簡単テク
import logging, os
level = logging.DEBUG if os.getenv("DEBUG") else logging.INFO
logging.basicConfig(level=level, format="%(asctime)s [%(levelname)s] %(name)s - %(message)s")
DEBUG=1 python app.py
で詳細ログを表示、通常はINFOレベル。
9️⃣ 便利ショートコード(貼って使う)
import logging
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s [%(levelname)s] %(name)s - %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
logger = logging.getLogger(__name__)
try:
logger.info("Start process")
1 / 0
except Exception:
logger.exception("error occurred")
🔟 便利ショートコード(ファイル出力バージョン)
import logging
# ログをコンソール + ファイルの両方に出力
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s [%(levelname)s] %(name)s - %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
handlers=[
logging.StreamHandler(), # コンソール出力
logging.FileHandler("app.log", encoding="utf-8") # ファイル出力
]
)
logger = logging.getLogger(__name__)
try:
logger.info("Start process")
1 / 0
except Exception:
logger.exception("Error occurred")
🧭 まとめ
| 目的 | 使う機能 | 一言メモ |
|---|---|---|
| 全体設定 | basicConfig |
一度だけ呼ぶ |
| モジュール別 | getLogger(__name__) |
慣例 |
| 例外出力 | logger.exception() |
トレース付 |
| コンソール+ファイル |
StreamHandler, FileHandler
|
よく使う組み合わせ |
| 追加情報 | extra |
%(key)s で出力 |
| ログ制御 | getLogger("lib").setLevel() |
サードパーティ対策 |
| テスト | caplog |
簡単に確認可能 |
🚀 結論
開発中はまずこれだけで十分:
import logging
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s [%(levelname)s] %(name)s - %(message)s",
)
logger = logging.getLogger(__name__)
必要に応じて:
-
FileHandler追加 → ローカルログ残す -
logger.exception→ エラー箇所確認 -
getLogger("urllib3").setLevel(WARNING)→ ノイズ削除
これを守るだけで、9割のPythonプロジェクトのloggingは解決します。