try / except / else / finally
| 対応: | Python 2(2000) |
|---|
Pythonの例外処理はtry/except構文で行います。エラーが発生しても処理を継続したい場合や、エラーに応じた処理を分岐したい場合に使います。例外を握りつぶす(何もしないexceptブロック)は避けることで、バグ発見が容易になります。elseは例外が発生しなかった場合に、finallyは例外の有無に関わらず必ず実行されます。
構文
try:
# 例外が発生する可能性のある処理
except 例外クラス as e:
# 例外発生時の処理
except (例外クラス1, 例外クラス2) as e:
# 複数の例外をまとめて処理
else:
# 例外が発生しなかった場合の処理
finally:
# 例外の有無に関わらず必ず実行される処理
# 例外を発生させる
raise 例外クラス("メッセージ")
キーワード一覧
| キーワード | 概要 |
|---|---|
| try | 例外が発生する可能性のある処理を囲むブロック。 |
| except 例外クラス | 指定した例外クラスが発生したときに実行するブロック。 |
| except Exception as e | 例外オブジェクトを変数eで受け取る。 |
| else | tryブロックで例外が発生しなかった場合に実行するブロック。 |
| finally | 例外の有無に関わらず必ず実行するブロック(リソース解放に使う)。 |
| raise | 意図的に例外を発生させる。 |
| Exception | 標準的な例外の基底クラス。 |
サンプルコード
try_basic.py
try:
result = 10 / 0
except ZeroDivisionError as e:
print(f"エラー: {e}")
def convert_to_int(value):
try:
return int(value)
except ValueError:
print(f"'{value}' は整数に変換できません")
return None
except TypeError:
print(f"型が不正です: {type(value).__name__}")
return None
print(convert_to_int('42'))
print(convert_to_int('abc'))
print(convert_to_int(None))
実行すると次のように出力されます。
python3 try_basic.py エラー: division by zero 42 'abc' は整数に変換できません None 型が不正です: NoneType None
try_else_finally.py
try:
num = int(input("数値を入力: "))
except ValueError:
print("数値ではありません")
else:
print(f"入力された数値: {num}")
file = None
try:
file = open('data.txt', 'r')
content = file.read()
except FileNotFoundError:
print("ファイルが見つかりません")
finally:
if file:
file.close()
実行すると次のように出力されます。
python3 try_else_finally.py 数値を入力: 42 入力された数値: 42
try_raise.py
def divide(a, b):
if b == 0:
raise ValueError("0で割ることはできません")
return a / b
try:
print(divide(10, 0))
except ValueError as e:
print(f"エラー: {e}")
try:
result = divide(10, 0)
except ValueError:
print("処理を記録しました")
raise
実行すると次のように出力されます。
python3 try_raise.py
エラー: 0で割ることはできません
処理を記録しました
Traceback (most recent call last):
File "try_raise.py", line 12, in <module>
result = divide(10, 0)
File "try_raise.py", line 3, in divide
raise ValueError("0で割ることはできません")
ValueError: 0で割ることはできません
よくあるミス
よくあるミス1: 裸のexceptでSystemExitまで捕捉してしまう
『except:』のみ(例外クラスを指定しない)と、SystemExitやKeyboardInterruptまで捕捉してしまいます。これらはプログラムの終了・割り込みのための例外なので、通常は捕捉すべきではありません。例外クラスを明示するか、少なくともExceptionを指定します。
try:
result = int(input("数値を入力: "))
except:
print("何かエラーが起きました")
次のように記述します。
try:
result = int(input("数値を入力: "))
except ValueError:
print("数値を入力してください")
よくあるミス2: except: passでエラーを握りつぶす
例外を捕捉しても何もしない(passのみ)と、エラーが発生していても気づかず、バグの発見が困難になります。最低限、エラー内容をログ出力するか、適切な処理を書きます。
try:
result = int(input("数値を入力: "))
except ValueError:
pass
次のように記述します。
try:
result = int(input("数値を入力: "))
except ValueError as e:
print(f"入力エラー: {e}")
result = 0
概要
exceptブロックは上から順に評価されるため、より具体的な例外クラスを先に書く必要があります。例えばExceptionはほぼすべての例外の基底クラスなので、先に書くと後続のexceptブロックが実行されません。
『else』ブロックは「tryが成功した場合に実行したいが、tryブロック自体には含めたくない処理」を記述するのに使います。これにより、エラーハンドリング対象の処理と成功後の処理を明確に分離できます。
ファイルやネットワーク接続などのリソース管理には、finallyを使う方法に加えて、『with』文(コンテキストマネージャ)を使った方法があります。withを使えばブロックの終了時に自動でリソースが解放されます。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。