Python/例外処理
例外処理(れいがいしょり、exception handling)とは、プログラム実行中に予期せぬ異常が発生した場合に、通常の実行フローを中断し、エラーメッセージの表示や適切な処理を行うプログラムの手法です。
raise
編集raise文は、プログラムの実行中に発生したエラーや問題を示し、その場で例外を引き起こします。例えば、条件に合致しない場合や予期せぬ状況であれば、raise文を使って例外を発生させることができます。
def reduce(array, callback, initialValue): if not callable(callback): raise ValueError(str(callback) + " is not a function") # ... reduce([], None, None)
- 実行結果
Traceback (most recent call last): File "Main.py", line 6, in <module> reduce([], None, None) File "Main.py", line 3, in reduce raise ValueError(str(callback) + " is not a function") ValueError: None is not a function
後述のtry/except
ブロックなしで raise
を実行すると、エラーが現在のコンテキストから伝播し、エラーが発生したポイントからコードの実行が停止されます。これにより、通常の実行フローが中断され、エラーがコンソールに表示されたり、上位の呼び出し元でエラーがキャッチされるまで、エラーが伝播します。
try節とexcept節
編集try
とexcept
は、Pythonにおける例外処理を行うための構文です。try
ブロック内のコードを実行し、もし例外が発生した場合に備えてそれをキャッチするためのものです。
基本的な構文は以下のようになります。
try: # ここに例外が発生する可能性のあるコードを記述する # 例外が発生した場合、次の行からの実行は中断される # 例外が発生しなければ、exceptブロックは実行されない except エラーの種類 as エラーオブジェクト: # 例外が発生した場合に行う処理を記述する # エラーの種類に応じて処理を変えることができる finally: # 必要に応じて、例外の発生に関わらず最後に実行される処理を記述する
例外が発生する可能性があるコードをtry
ブロックに記述し、もし例外が発生した場合、その種類に応じたexcept
ブロックが実行されます。except
ブロックでは例外の種類を指定し、その例外が発生した際に実行するコードを記述します。
例えば:
try: result = 10 / 0 # ゼロ除算の例外が発生する可能性があるコード except ZeroDivisionError as e: print("エラーが発生しました:", e)
この例では、ゼロ除算の例外が発生する可能性があるため、try
ブロックで計算を行っています。もしゼロ除算のエラーが発生すれば、except
ブロックが実行され、エラーメッセージが表示されます。
else節とfinally節
編集Pythonの例外処理には、try
やexcept
に加えてelse
節とfinally
節もあります。else
節は、try
ブロック内で例外が発生しなかった場合に実行される部分です。
基本的な構文は次のようになります:
try: # 例外が発生する可能性のあるコード except エラーの種類 as エラーオブジェクト: # 例外が発生した場合の処理 else: # 例外が発生しなかった場合の処理 finally: # 例外の有無に関わらず最後に実行される処理
else
節は、try
ブロック内で例外が発生せず、正常に処理が完了した場合に実行されます。例外が発生した場合はexcept
ブロックが実行され、例外が発生しなかった場合はelse
ブロックが実行されるという流れです。
例えば:
try: result = 10 / 2 # 例外が発生しないようなコード except ZeroDivisionError as e: print("ゼロ除算エラー:", e) else: print("計算結果:", result) finally: print("処理が完了しました")
この例では、try
ブロック内でゼロ除算が行われていないため、except
ブロックは実行されず、代わりにelse
ブロックが実行され、計算結果が表示されます。最後にfinally
ブロックが実行され、"処理が完了しました"というメッセージが表示されます。
return と finally
編集- return と finally
def div(n, d) : try : return n / d except Exception as e: print(e) finally : print("div(%s, %s) -- finally" % (n, d)) print("div(1, 2) = %s" % div(1, 2)) print("div(1, 0) = %s" % div(1, 0)) print("div(0, 0) = %s" % div(0, 0))
- 実行結果
div(1, 2) -- finally div(1, 2) = 0.5 division by zero div(1, 0) -- finally div(1, 0) = None division by zero div(0, 0) -- finally div(0, 0) = None
- try文にfinally節を持つ言語では「tryブロックで例外を出さずのreturn文に達したとき、finally節を実行するか?」が問題になります。
- Puthonでは、return文に達してもfinally節が実行されます。
例外の場合わけ
編集Pythonにおける例外の場合分けは、try
とexcept
を使用して行います。except
ブロックは、特定の例外が発生した場合にそれをキャッチして処理するために使用されます。また、except
ブロックは複数指定することもできます。
例えば:
try: result = 10 / 0 # 例外が発生する可能性のあるコード except ZeroDivisionError as e: print("ゼロ除算エラー:", e) except TypeError as e: print("型エラーが発生しました:", e) except Exception as e: print("予期せぬエラーが発生しました:", e)
上記の例では、try
ブロック内でゼロ除算が行われています。しかし、ZeroDivisionError
以外のエラーが発生する可能性もあるため、複数のexcept
ブロックで異なる例外をキャッチするようにしています。except
ブロックの最後にException
を指定することで、すべての予期せぬ例外をキャッチすることができます。
また、except
ブロックで例外をキャッチするだけでなく、例外の情報を取得したり、適切な処理を行ったりすることもできます。
try: num = int(input("数字を入力してください: ")) result = 10 / num print("計算結果:", result) except ValueError: print("無効な値が入力されました。整数を入力してください。") except ZeroDivisionError: print("ゼロで除算することはできません。") else: print("正常に計算が完了しました。") finally: print("プログラムの実行が終了しました。")
この例では、ユーザーから整数の入力を受け取り、その入力に応じて計算を行います。ValueError
やZeroDivisionError
などの特定の例外に応じてメッセージを表示し、それぞれの状況に適した対処を行っています。else
ブロックは例外が発生しなかった場合に実行され、finally
ブロックは最後に必ず実行されます。
組込み例外一覧
編集__builtins__ の要素のうち BaseExceptionのサブクラスを例外とし、例外と例外の __doc__ を表にしました。
- 組込み例外一覧
#print(issubclass(ValueError, Exception)) ex = [] for k in vars(__builtins__): try: if eval(f"issubclass({k}, BaseException)"): ex.append(k) except TypeError: pass print(f"""\ {{| class=wikitable |+ 組込み例外 !例外!!__doc__\ """) for k in sorted(ex): print(f"""\ |- ! {k} | {eval(f"{k}.__doc__")}\ """) print("|}")
このコードは、Pythonの__builtins__
モジュール内の組み込み例外クラスを取得しています。具体的には、BaseException
クラスを継承している例外クラスを収集してリストに追加しています。
以下、このコードの動作を詳しく説明します。
__builtins__
モジュールにはPythonの組み込み関数や組み込み例外が含まれています。vars(__builtins__)
を使うことで、__builtins__
モジュール内の変数(関数やクラスなど)の辞書を取得できます。- ループを使って
vars(__builtins__)
内の各要素(k
)に対して処理を行います。 issubclass()
関数は、1つのクラスが別のクラスのサブクラスであるかどうかを確認します。eval()
関数を使って文字列をPythonコードとして評価し、issubclass()
を使ってBaseException
クラスを継承しているかどうかを確認します。BaseException
クラスを継承している場合、その例外クラス名をリストex
に追加します。try
ブロック内でTypeError
が発生した場合(例外クラスがissubclass()
に適合しない場合)、except
ブロックでpass
を使って何もせずにスキップします。
つまり、このコードは組み込みの例外クラスを調べ、BaseException
クラスを継承しているものをリストex
に追加するものです。例外ハンドリングや特定の例外クラスに対する処理を行う際に、組み込みの例外クラスを動的に取得する際に役立ちます。
組込み例外 例外 __doc__ ArithmeticError Base class for arithmetic errors. AssertionError Assertion failed. AttributeError Attribute not found. BaseException Common base class for all exceptions BlockingIOError I/O operation would block. BrokenPipeError Broken pipe. BufferError Buffer error. BytesWarning Base class for warnings about bytes and buffer related problems, mostly related to conversion from str or comparing to str.
ChildProcessError Child process error. ConnectionAbortedError Connection aborted. ConnectionError Connection error. ConnectionRefusedError Connection refused. ConnectionResetError Connection reset. DeprecationWarning Base class for warnings about deprecated features. EOFError Read beyond end of file. EnvironmentError Base class for I/O related errors. Exception Common base class for all non-exit exceptions. FileExistsError File already exists. FileNotFoundError File not found. FloatingPointError Floating point operation failed. FutureWarning Base class for warnings about constructs that will change semantically in the future.
GeneratorExit Request that a generator exit. IOError Base class for I/O related errors. ImportError Import can't find module, or can't find name in module. ImportWarning Base class for warnings about probable mistakes in module imports IndentationError Improper indentation. IndexError Sequence index out of range. InterruptedError Interrupted by signal. IsADirectoryError Operation doesn't work on directories. KeyError Mapping key not found. KeyboardInterrupt Program interrupted by user. LookupError Base class for lookup errors. MemoryError Out of memory. ModuleNotFoundError Module not found. NameError Name not found globally. NotADirectoryError Operation only works on directories. NotImplementedError Method or function hasn't been implemented yet. OSError Base class for I/O related errors. OverflowError Result too large to be represented. PendingDeprecationWarning Base class for warnings about features which will be deprecated in the future.
PermissionError Not enough permissions. ProcessLookupError Process not found. RecursionError Recursion limit exceeded. ReferenceError Weak ref proxy used after referent went away. ResourceWarning Base class for warnings about resource usage. RuntimeError Unspecified run-time error. RuntimeWarning Base class for warnings about dubious runtime behavior. StopAsyncIteration Signal the end from iterator.__anext__(). StopIteration Signal the end from iterator.__next__(). SyntaxError Invalid syntax. SyntaxWarning Base class for warnings about dubious syntax. SystemError Internal error in the Python interpreter. Please report this to the Python maintainer, along with the traceback, the Python version, and the hardware/OS platform and version.
SystemExit Request to exit from the interpreter. TabError Improper mixture of spaces and tabs. TimeoutError Timeout expired. TypeError Inappropriate argument type. UnboundLocalError Local name referenced but not bound to a value. UnicodeDecodeError Unicode decoding error. UnicodeEncodeError Unicode encoding error. UnicodeError Unicode related error. UnicodeTranslateError Unicode translation error. UnicodeWarning Base class for warnings about Unicode related problems, mostly related to conversion problems.
UserWarning Base class for warnings generated by user code. ValueError Inappropriate argument value (of correct type). Warning Base class for warning categories. ZeroDivisionError Second argument to a division or modulo operation was zero.