HOWTO · Python
Python で例外を出力する方法
Python で例外を出力し、メッセージと完全なトレースバックを使い分け、よくある例外処理のミスを避ける方法を説明します。
このページの内容
エラーメッセージだけが必要なら print(exception) を使います。エラーを発生させたファイルと行を含む完全なトレースバックが必要なら、実行中の except ブロック内で traceback.print_exc() を使います。例外の種類を限定して処理し、保存する診断情報には print() ではなくロギングを使います。
例外のメッセージを出力する
例外を変数として受け取り、print() に渡します。何が起きたかを表示する最短の方法です。
try:
result = 10 / 0
except ZeroDivisionError as exc:
print("Could not calculate result:", exc)
出力:
Could not calculate result: division by zero
例外オブジェクトはメッセージの文字列に変換されます。この例は ZeroDivisionError だけを捕捉するため、無関係なプログラミングエラーを隠しにくくなります。複数のエラーを同じように扱う場合は、except (TypeError, ValueError) as exc: のように型をタプルで指定します。
完全なトレースバックを出力する
メッセージだけでは、エラーが発生した場所が分からないことがあります。Python 標準の traceback モジュールを読み込み、ハンドラーが有効な間に print_exc() を呼び出します。
import traceback
try:
values = [1, 2]
value = values[3]
except IndexError:
traceback.print_exc()
出力には例外の型、メッセージ、ファイル、失敗した行が含まれます。複数の関数呼び出しを経た例外では、メッセージよりトレースバックの方が役立ちます。
print_exc() は現在処理中の例外を読み取ります。except ブロックの終了後や、例外が有効でないときに呼び出しても過去のトレースバックは復元できず、NoneType: None が出力されることがあります。呼び出しをハンドラー内に置くか、例外を保存して print_exception() を使います。
トレースバックの形式を明示的に制御する
traceback.print_exception() は例外オブジェクトを受け取り、指定したストリームに書き込めます。例外を整形したり転送したりする場合に便利です。
import sys
import traceback
try:
int("not a number")
except ValueError as exc:
traceback.print_exception(exc, file=sys.stdout)
すぐに出力せずテキストを作るには、traceback.format_exception(exc) を使います。
import traceback
try:
raise RuntimeError("configuration is missing")
except RuntimeError as exc:
formatted = "".join(traceback.format_exception(exc))
print(formatted)
traceback の関数は既定で例外の連鎖を保持します。そのため raise ... from ... の連鎖では元の例外と新しい例外の両方が表示されます。出力仕様で必要な場合だけトレースバックを制限したり連鎖を無効にしたりしてください。コンテキストを失うと診断が難しくなります。
独自例外とロギング
呼び出し側がドメイン固有の失敗と組み込みエラーを区別する必要がある場合は、独自例外を定義します。その型を捕捉し、同じ方法でメッセージを出力します。
class ConfigurationError(Exception):
pass
try:
raise ConfigurationError("API key is missing")
except ConfigurationError as exc:
print("Configuration failed:", exc)
アプリケーションやサービスでは、ハンドラー内の logging.exception() を優先します。メッセージと有効なトレースバックを記録し、ログの出力先をファイルや監視システムにできます。
import logging
try:
load_settings()
except Exception:
logging.exception("Loading settings failed")
load_settings() は失敗する可能性のある処理に置き換えます。この例が広い Exception を捕捉するのはロギング境界だからです。通常の処理では、実際に扱える具体的な例外だけを捕捉します。
よくあるミスと FAQ
- 型を指定しない
except:はKeyboardInterruptとSystemExitも捕捉します。BaseExceptionのサブクラスを扱う明確な理由がない限り避けます。 - 有効な結果を作れないのに一般的なメッセージだけを出して黙って続行しないでください。例外を再送出するか、明示的な失敗を返します。
type(exc)は具体的なクラス、str(exc)は人が読めるメッセージ、repr(exc)はより診断的な表現を示します。- ログに出力するならハンドラー内で
logging.exception()を使います。短い対話的な診断ならprint(exc)で十分です。 traceback.print_exc()は現在処理中の例外用です。例外オブジェクトを保持して形式や出力を制御するならtraceback.print_exception(exc)の方が明確です。
これらは Python 組み込みの例外機構を使うため、サードパーティーパッケージは不要です。必要なのがメッセージ、完全な呼び出し経路、整形済みテキスト、永続的なログのどれかで方法を選びます。