【Python】try-exceptでエラー内容を取得・表示する方法

【Python】try-exceptでエラー内容を取得・表示する方法

公開: 更新:
CodeCampが提供するDX人材育成が可能なプログラミングやITが学べる公開講座

Pythonで実行時に発生するエラーは、try-except文を使うことによって捕捉できます。しかし、エラーが発生したことはわかっても、具体的にどのようなエラーが起きたのかを把握できなければ、適切な対処は困難です。

try-except文ではexcept Exception as eのように記述することによって、例外オブジェクト変数に格納できます。例外オブジェクトとは、エラー発生時にPythonが自動的に生成するオブジェクトのことで、エラーメッセージや名などの詳細情報を保持しています。

この記事では、try-exceptでエラー内容を取得する具体的な方法を、実践的なサンプルコードとともに解説していきます。



Pythonのtry-exceptでエラー内容を取得する方法

try-except文でエラー内容を取得するには、exceptasキーワードを使って例外オブジェクトを変数に代入します。基本的な構文は、以下の通りです。

try:
    # エラーが発生する可能性のある処理
except 例外型 as 変数名:
    # エラー内容を使った処理

代入された例外オブジェクトはargs属性にコンストラクタへ渡された引数を保持しています。この例外オブジェクトをstr()repr()type()などと組み合わせることで、用途に応じたエラー情報を取り出せます。

The except clause may specify a variable after the exception name. The variable is bound to the exception instance which typically has an args attribute that stores the arguments.

出典:Python公式ドキュメント - Errors and Exceptions

ここでは代表的な3つの取り出し方として、str(e)repr(e)type(e).__name__の使い分けを見ていきます。

str(e)でエラーメッセージを文字列として取得する

str(e)は、例外オブジェクトを文字列に変換して、エラーの概要を取得する方法です。ユーザーへのエラー通知やログ出力など、エラーの内容を簡潔に確認したい場面で使用します。

try:
    number = int("abc")
except ValueError as e:
    print(str(e))

上記のコードでは、文字列"abc"整数に変換しようとしてValueErrorが発生します。str(e)を使うことによって、invalid literal for int() with base 10: 'abc'というエラーメッセージが出力されます。

str(e)が返す文字列は、例外オブジェクトの__str__()メソッドの実装に依存しており、通常はコンストラクタに渡された引数(args)の内容をもとに生成されます。組み込み例外のほとんどは人間が読みやすいメッセージを返すため、簡易的なエラー通知に適しています。

ただし、例外の型名は含まれないため、どの種類のエラーが発生したかも併せて確認したい場合には不向きです。型名を含めて出力したい場合は、次に紹介するrepr(e)type(e).__name__を使用してください。

repr(e)でエラーの型名と引数を含む表現を取得する

repr(e)は、例外オブジェクトの「公式な文字列表現」を返す方法です。多くの組み込み例外ではクラス名(引数)という形式で出力されるため、例外の型名と内容をまとめて1行で確認したい場面で使用します。

try:
    result = 10 / 0
except ZeroDivisionError as e:
    print(repr(e))

上記のコードを実行すると、ZeroDivisionError('division by zero')と出力されます。str(e)とは異なり、先頭にZeroDivisionErrorという例外クラス名が付与されるため、エラーの種類をひと目で確認できます。

repr(e)が返す内容は、BaseException__repr__()の実装に基づくもので、厳密には「型名 + コンストラクタに渡された引数(args)の表現」です。ただし、Pythonの標準的な例外では引数にエラーメッセージが渡されるため、結果として型名とメッセージを同時に確認できる表現になり、ログに1行で記録しておきたい用途に便利です。


Python研修一覧はこちら

目的に合うPython研修を一覧形式から探したい方は、ぜひご利用ください。

Python研修を比較する

Java研修一覧はこちら

目的に合うJava研修を一覧形式から探したい方は、ぜひご利用ください。

Java研修を比較する

PHP研修一覧はこちら

目的に合うPHP研修を一覧形式から探したい方は、ぜひご利用ください。

PHP研修を比較する

新入社員研修

目的に合う新入社員研修を一覧形式から探したい方は、ぜひご利用ください。

新入社員研修を比較する

全ての研修からも探したい方はこちら

type(e).__name__でエラーの型名だけを取得する

type(e).__name__は、例外オブジェクトの型名(クラス名)だけを文字列として取得する方法です。ログにエラー型名をフォーマットに合わせて記録したい場合や、エラー型名と本文を別々に扱いたい場面で使用します。

try:
    data = {"key": "value"}
    print(data["nonexistent"])
except KeyError as e:
    error_type = type(e).__name__
    error_message = str(e)
    print(f"エラー型: {error_type}")
    print(f"エラー内容: {error_message}")

上記のコードでは、辞書に存在しないキーを参照してKeyErrorが発生します。type(e).__name__KeyErrorという型名を取得し、str(e)でエラーメッセージを取得することによって、出力のフォーマットを自由に制御できます。

なお、エラーの種類に応じて処理を分岐させたい場合、type(e).__name__で取得した文字列を比較する方法は推奨されません。タイプミスによるバグの原因になるうえ、継承関係が考慮されないためです。

例外処理の分岐は、後述する複数のexcept節を型ごとに書く方法を第一選択肢としてください。すでに捕捉済みの例外をさらに細かく分類したい特殊なケースに限って、isinstance(e, SomeError)による型チェックを補助的に使う場面があります。

tracebackモジュールでエラーの発生箇所を特定する方法

tracebackモジュールとは、Pythonの標準ライブラリに含まれるモジュールで、例外発生時のスタックトレース(関数の呼び出し履歴)を取得・表示する機能を提供します。str(e)repr(e)ではエラーメッセージや型名は取得できますが、エラーがコードのどの行で発生したかまでは確認できません。

tracebackモジュールを使うことによって、エラーの発生箇所をファイル名・行番号・関数名とともに特定できます。ここでは、出力先が異なる2つの関数traceback.format_exc()traceback.print_exc()の使い分けを解説します。

いずれも「現在処理中の例外」に対して動作する関数のため、except節の中で呼び出すのが基本です。except節の外で呼び出すと、直前の例外情報に依存したり、意図した結果が得られなかったりする可能性があります。

traceback.format_exc()でトレースバック全体を文字列として取得する

traceback.format_exc()は、現在処理中の例外のトレースバック情報を文字列として返す関数です。戻り値が文字列であるため、変数に格納してログファイルへの書き出しやメール通知など、さまざまな用途に活用できます。

import traceback

def divide(a, b):
    return a / b

try:
    result = divide(10, 0)
except ZeroDivisionError:
    error_detail = traceback.format_exc()
    print(error_detail)

上記のコードを実行すると、以下のようなトレースバック情報が出力されます。ファイル名・行番号・関数名・エラーメッセージが含まれるため、エラーの発生箇所を正確に特定できます。

Traceback (most recent call last):
  File "example.py", line 6, in <module>
    result = divide(10, 0)
  File "example.py", line 4, in divide
    return a / b
ZeroDivisionError: division by zero

traceback.format_exc(limit=None, chain=True) - Format the exception information and stack trace entries from the current exception, as a string.

出典:Python公式ドキュメント - traceback — Print or retrieve a stack traceback

str(e)だけでは発生箇所がわからないエラーも、format_exc()なら原因の特定が容易です。本番環境でエラー内容を保存したい場合は、単純なopen()による書き出しよりも、後述のloggingモジュールを使う方が一般的です。

traceback.print_exc()でトレースバックを標準エラー出力に表示する

traceback.print_exc()は、現在処理中の例外のトレースバック情報を、既定で標準エラー出力(sys.stderr)に直接表示する関数です。format_exc()が文字列を返すのに対して、print_exc()は表示まで自動的に行うため、デバッグ中にすぐ結果を確認したい場面で使用します。

import traceback

try:
    numbers = [1, 2, 3]
    print(numbers[10])
except IndexError:
    print("エラーが発生しました。詳細は以下の通りです。")
    traceback.print_exc()

上記のコードでは、リストの範囲外のインデックスにアクセスしてIndexErrorが発生します。traceback.print_exc()を呼び出すことによって、トレースバック情報がそのまま標準エラー出力に表示されます。

print()による出力は通常sys.stdoutに送られるのに対し、print_exc()は既定でsys.stderrに出力される点に注意してください。なお、キーワード引数fileにファイルオブジェクトを指定することで、出力先を変更することも可能です。

ただし、実務でのログ記録には、後述するloggingモジュールを使う方法が一般的です。


Python基礎・実践(Django)

企業・法人向けのPython研修では、基礎から応用まで体系的に学べます。

Python研修の詳細

DX社員研修

企業・法人向けのDX研修では、実務に繋がるリスキリングでITレベルを向上させます。

DX研修の詳細

Javaエンジニア育成研修

企業・法人向けのJavaエンジニア育成研修では、Javaの基礎から応用まで確実に習得できます。

Java研修の詳細

新卒・新入社員向け研修

企業・法人に新入社員・新卒社員に向けたプログラミング研修を提供しています。

新入社員研修の詳細

コードキャンプのIT研修を全て見る

複数の例外を個別に捕捉してエラー内容を取得する方法

実際のプログラムでは、1つのtryブロック内で複数の種類のエラーが発生する可能性があります。エラーの種類ごとに異なるメッセージを表示したり、処理を分岐させたりしたい場合は、複数のexcept節を使って個別に捕捉します。

方法は大きく分けて、型ごとにexcept節を分ける方法と、1つのexcept節にタプルで複数の例外型を指定する方法の2つです。ここから、それぞれの書き方と使い分けのポイントを解説します。

例外の型ごとにexcept節を分けて処理する

except節を複数記述することによって、例外の型ごとに異なる処理を実行できます。エラーの種類に応じてユーザーへのメッセージを変えたい場合や、リカバリ処理を分岐させたい場合に使用します。

def process_data(value, index):
    try:
        numbers = [10, 20, 30]
        result = numbers[index] / value
        return result
    except ZeroDivisionError as e:
        print(f"ゼロ除算エラー: {str(e)}")
        return None
    except IndexError as e:
        print(f"インデックスエラー: {str(e)}")
        return None
    except Exception as e:
        print(f"予期しないエラー: {repr(e)}")
        return None

print(process_data(0, 1))
print(process_data(2, 5))

上記のコードでは、ZeroDivisionErrorとIndexErrorをそれぞれ個別のexcept節で捕捉しています。最後のexcept Exception as eは、想定外の通常エラーを広く捕捉するためのフォールバックとして機能します。

ただし、KeyboardInterrupt(Ctrl+Cによる中断)やSystemExit(プログラムの終了要求)などはBaseExceptionの直下に位置し、Exceptionのサブクラスではないため、この書き方では捕捉されません。この点はexcept Exceptionの仕様として押さえておきましょう。

except節は上から順に評価されるため、具体的な例外型を先に記述し、汎用的なExceptionは最後に配置してください。順序を逆にすると、具体的な例外型のexcept節に到達する前にExceptionで捕捉されてしまい、個別の処理が実行されません。

1つのexcept節で複数の例外型をまとめて捕捉する

複数の例外型に対して同じ処理を行いたい場合は、except節にタプルで例外型を指定することによって、1つのexcept節でまとめて捕捉できます。エラーの種類に関わらず共通のエラーハンドリングを行う場面で使用します。

def read_config(filepath, key):
    try:
        with open(filepath, "r") as f:
            config = {}
            for line in f:
                k, v = line.strip().split("=")
                config[k] = v
            return config[key]
    except (FileNotFoundError, KeyError, ValueError) as e:
        error_type = type(e).__name__
        print(f"設定読み込みエラー [{error_type}]: {str(e)}")
        return None

result = read_config("config.txt", "database_host")
print(result)

上記のコードでは、FileNotFoundErrorやKeyError、ValueErrorの3種類の例外を1つのexcept節でまとめて捕捉しています。type(e).__name__を使うことによって、実際に発生した例外の型名をエラーメッセージに含めています。

タプルで指定する方法は、コードの重複を減らしてメンテナンス性を向上させる効果があります。ただし、例外の種類ごとに異なるリカバリ処理が必要な場合は、前述のようにexcept節を分けて記述してください。

Pythonのtry-exceptに関するよくある質問

except Exceptionとexceptだけの違いは何ですか?

except ExceptionExceptionクラスとそのサブクラスのみを捕捉するのに対し、exceptだけの記述(bare except)はBaseExceptionを含むすべての例外を捕捉します。bare exceptはKeyboardInterrupt(Ctrl+Cによる中断)やSystemExit(プログラムの終了要求)まで捕捉してしまうため、PEP 8でも使用を避けるべきとされています。

広めに捕捉したい場合はexcept Exceptionを使い、原則としては想定される具体的な例外型を指定するのが推奨されるスタイルです。

エラー内容をファイルに書き出す方法はありますか?

本番環境でのエラー記録には、Pythonの標準ライブラリであるloggingモジュールのlogging.exception()メソッドを使うのが一般的です。あらかじめlogging.basicConfig()などでファイル出力先をハンドラとして設定したうえで、except節の中でこのメソッドを呼び出すことによって、タイムスタンプ付きでエラーメッセージとトレースバックをログファイルへ記録できます。

設定を行わない場合は既定のハンドラによって標準エラー出力に表示されるだけで、ファイルには書き出されない点に注意してください。簡易的に対応したい場合は、traceback.format_exc()で取得したトレースバック文字列をopen()関数でファイルへ書き出す方法もあります。

※上記コンテンツの内容やソースコードはAIで確認・デバッグしておりますが、間違いやエラー、脆弱性などがある場合は、コメントよりご報告いただけますと幸いです。

ITやプログラミングに関するコラム


ITやプログラミングに関するニュース

ブログに戻る

コメントを残す

コメントは公開前に承認される必要があることにご注意ください。

企業・法人向けのIT・プログラミング・生成AI研修を探す、比較する - IT・プログラミングを知って学べるコネクトメディア CodeCampが提供するDX人材育成が可能なプログラミングやITが学べる公開講座 - IT・プログラミングを知って学べるコネクトメディア コードキャンプが提供する無料で学べるプログラミングスクール講座 - IT・プログラミングを知って学べるコネクトメディア コードキャンプDX人材育成研修 - IT・プログラミングを知って学べるコネクトメディア 3.5日の研修で、年間1,600時間の削減効果が見込まれる。東京きらぼしフィナンシャルグループのDX人材育成事例 - IT・プログラミングを知って学べるコネクトメディア 配属3ヶ月で30%の生産性向上を実現するいよぎんコンピュータサービスの新人研修に迫る - IT・プログラミングを知って学べるコネクトメディア 金融業界の業務効率化を加速するニッセイアセットマネジメントの生成AI×GAS活用研修事例 - IT・プログラミングを知って学べるコネクトメディア 【製造業のDX人材育成事例】デジタル人材の即戦力化を実現する、日本ガイシ株式会社の異動者向オンボーディング研修 - ITやプログラミングを知って学べるコネクトメディア フューチャーアーキテクト株式会社が実現した新入社員向けIT研修プログラムでタスクフォース制度が主体的な学びと成長を生み出す - IT・プログラミングを知って学べるコネクトメディア コードキャンプDX人材育成研修 - IT・プログラミングを知って学べるコネクトメディア コードキャンプIT・プログラミング研修事例/【IT新入社員研修】オンラインとオフラインの最適バランスを実現したFutureOneの導入事例 - IT・プログラミングを知って学べるコネクトメディア コードキャンプIT・プログラミング研修事例/【新入社員研修】柔軟なハイブリッド型Java研修で実現した新卒20名の成長と成果|サークレイス株式会社 - ITやプログラミングを知って学べるコネクトメディア コードキャンプIT・プログラミング研修事例/現場により近いところにデジタルを根付かせるDX基礎講座研修|株式会社ブリヂストン - ITやプログラミングを知って学べるコネクトメディア コードキャンプIT・プログラミング研修事例/業務の効率化・DX推進に向けたIT人材育成への第一歩|株式会社カナエ - ITやプログラミングを知って学べるコネクトメディア 企業・法人向けのIT・プログラミング研修 - ITやプログラミングを知って学べるコネクトメディア

新着記事

対象者別で探す

子供(小学生・中学生・高校生)向け
プログラミング教室検索する

子供(小学生・中学生・高校生)がロボットやプログラミング言語を学ぶことができるオフラインからオンラインスクールを検索、比較することが可能です。

子供(小学生・中学生・高校生)
プログラミング教室検索する

ITやプログラムなどの
最新情報を検索する

日々、新しいITやプログラミング言語の情報が流れていきますが、特定の情報を時系列でニュースやコラムを確認することができます。

ITやプログラムなどの
最新情報を検索する