Python traceback.format_exc()とは?トレースバックを文字列で取得する方法
traceback.format_exc()は、トレースバックを文字列として取得する関数です。
画面に出すのではなくログ・DB・通知サービスに送りたいときに使います。
format_exc()の基本
import traceback
def f():
return 1 / 0
try:
f()
except ZeroDivisionError:
s = traceback.format_exc()
print("型:", type(s).__name__)
print(s, end="")
実行結果:
型: str
Traceback (most recent call last):
File "demo2.py", line 7, in <module>
f()
File "demo2.py", line 4, in f
return 1 / 0
ZeroDivisionError: division by zero
戻り値はstrです。末尾に改行が含まれるため、print()にはend=""を付けると二重改行を防げます。
print_exc()との違い
print_exc() |
format_exc() |
|
|---|---|---|
| 動き | 表示する | 文字列を返す |
| 出力先 | 標準エラー出力 | なし |
| 加工 | できない | できる |
内容は同じです。「出す」か「受け取る」かの違いだけです。
文字列で受け取れば、ログに書く・DBに保存する・Slackに送る——何でもできます。
ログに残す
import traceback
import logging
for item in items:
try:
process(item)
except Exception:
logging.error("失敗: %s\n%s", item, traceback.format_exc())
どの項目で失敗したかを一緒に残せます。
これがformat_exc()の典型的な使い方です。トレースバックだけでは「どのデータで落ちたのか」が分かりません。
ただし、loggingには専用の書き方もあります。
logging.exception("失敗: %s", item)
こちらのほうが簡潔です。format_exc()を呼ばなくてもトレースバックが付きます。
ではformat_exc()はいつ使うのか——ログ以外に送るときです。
通知やDBに送る
import traceback
try:
処理()
except Exception as e:
record = {
"type": type(e).__name__,
"message": str(e),
"traceback": traceback.format_exc(),
}
save_to_db(record)
notify_slack(record)
構造化して保存できます。
例外の種類・メッセージ・トレースバックを分けて持てば、あとから種類ごとに集計できます。
JSONにするなら、そのままjson.dumps()に渡せます。
「Python json.dumps()とは?辞書をJSON文字列に変換する方法」を参照してください。
ユーザーには見せない
重要な注意点です。
トレースバックには次の情報が含まれます。
- サーバー上のファイルパス(ディレクトリ構成が分かる)
- 使っているライブラリとその位置
- ソースコードの一部
- 変数名や処理の流れ
Webアプリでこれをそのまま返すと、攻撃の手がかりを与えることになります。
try:
処理()
except Exception:
logging.exception("内部エラー") # 詳細はログへ
return "エラーが発生しました", 500 # 利用者には最小限
詳細はログに、利用者には一般的なメッセージを。これが原則です。
行ごとに扱う
import traceback
import sys
try:
f()
except ZeroDivisionError:
et, ev, tb = sys.exc_info()
lines = traceback.format_exception(et, ev, tb)
print("型:", type(lines).__name__, "要素数:", len(lines))
for i, l in enumerate(lines):
print(f"[{i}]", repr(l))
実行結果:
型: list 要素数: 4
[0] 'Traceback (most recent call last):\n'
[1] ' File "demo3.py", line 5, in <module>\n f()\n'
[2] ' File "demo3.py", line 2, in f\n return 1/0\n'
[3] 'ZeroDivisionError: division by zero\n'
format_exception()はリストで返します。最終行だけ取り出すといった加工ができます。
print(lines[-1].strip())
実行結果:
ZeroDivisionError: division by zero
Python 3.10以降はformat_exception(e)と例外オブジェクト1つだけでも呼べます。3.9以前は3引数が必要です。
format_exc()のまとめ
- トレースバックを文字列で返す
- 内容は
print_exc()と同じ——出すか受け取るかの違い - ログだけなら
logging.exception()が簡潔 - DB・通知に送るときに真価を発揮
- 利用者に見せてはいけない(パスやコードが漏れる)
- 行ごとに扱うなら
format_exception()





