【Python】 エラーとその処理を解説 「構文エラー ( SyntaxError )」と「例外 (Exception)」 例外処理「try-except」構文など

Pythonのコードにおけるエラーについて解説します。
エラーは大きく分けて「構文エラー」と「例外」の2種類に分類されます。それぞれについて、詳しく説明していきます。

構文エラー ( SyntaxError )

構文エラーは、Pythonの文法に違反しているコードを書いた場合に発生します。
このエラーは、プログラムが実行される前に検出され、プログラムが正しく動作することを防ぎます。例えば、if文のコロンを忘れたり、括弧の対応が取れていない場合などに発生します。

コピーしました!

python
if True
    print("これは構文エラーです")

  File “/tmp/ipykernel_3534/1352356341.py”, line 1
    if True
           ^
SyntaxError: invalid syntax

上記のコードはif文の後にコロン(:)が抜けているため、SyntaxError: invalid syntaxというエラーが発生します。構文エラーは、通常、エディタやIDEでコーディング中に自動的に検出されます。

例外 (Exception)

例外はコードが正しい構文に従って書かれていても、実行時に発生する問題です。
例えば、存在しないファイルへのアクセスなどが例外を引き起こします。
Pythonでは多くの種類の例外が定義されており、いくつかの具体例を紹介します。

例外の具体例

  1. ZeroDivisionError: ゼロで除算しようとしたときに発生します。

コピーしました!

python
x = 1 / 0  # ZeroDivisionError

—————————————————————————
ZeroDivisionError                         Traceback (most recent call last)
/tmp/ipykernel_3534/3501548725.py in <cell line: 1>()
—-> 1 x = 1 / 0  # ZeroDivisionError
ZeroDivisionError: division by zero

  1. FileNotFoundError: 存在しないファイルを開こうとしたときに発生します。

コピーしました!

python
with open('non_existent_file.txt', 'r') as f:
    data = f.read()  # FileNotFoundError

FileNotFoundError Traceback (most recent call last)
/tmp/ipykernel_3534/1725794067.py in ()
—-> 1 with open(‘non_existent_file.txt’, ‘r’) as f:
2 data = f.read() # FileNotFoundError

FileNotFoundError: [Errno 2] No such file or directory: ‘non_existent_file.txt’

  1. TypeError: 不適切な型が使われたときに発生します。
python
x = 'string' + 5  # TypeError

—————————————————————————
TypeError                                 Traceback (most recent call last)
/tmp/ipykernel_3534/2455920911.py in <cell line: 1>()
—-> 1 x = ‘string’ + 5  # TypeError
TypeError: can only concatenate str (not “int”) to str

コピーしました!

他にも次のようなエラーがあります。
NameError: 名前が定義されていないときに発生します。
IndexError: 要素が存在しないときに発生します。
ValueError: 型を変換できないときに発生します。
RuntimeError: ソフトウェアやハードウェアに問題があるときに発生します。

例外処理: try-except構文

Pythonでは、例外が発生した場合でもプログラムが停止しないようにすることができます。

try-except構文で例外を処理できます。以下は基本的なtry-except構文の例です。

コピーしました!

python
try:
    x = 1 / 0
except ZeroDivisionError:
    print("ゼロで割ることはできません")

このコードは、ゼロ除算を試みますが、ZeroDivisionErrorを捕捉し、適切なメッセージを表示してプログラムを終了させずに処理します。

elseを使った例外の処理

elseを使い、例外が起きなかったときに実行する処理を加えることも可能です。例として、分母に任意の値を加え、除算を行うコードを書いてみます。

コピーしました!

python
x=int(input())
y=int(input())

try:
    x /y
except :
    print("ゼロで割ることはできません")
else :
    print("計算できました。")

raise文を使った例外の送出

自分で例外を送出することも可能です。例えば、特定の条件が満たされない場合に例外を送出するようなコードです。

コピーしました!

python
def check_age(age):
    if age < 18:
        raise ValueError("年齢が18未満です")
    return "年齢確認済み"

try:
    print(check_age(15))
except ValueError as e:
    print(e)

このコードでは、18歳未満の場合にValueErrorを発生させ、それをexceptでキャッチしています。

Raise文は例外の検出等に使われます。

例外の連鎖 (from を使う)

Pythonでは、ある例外が別の例外の結果として発生する場合に、例外を連鎖させることができます。これにはfromを使います。

コピーしました!

python
try:
    raise ValueError("元のエラー")
except ValueError as e:
    raise RuntimeError("新しいエラー") from e

—————————————————————————
ValueError                                Traceback (most recent call last)
/tmp/ipykernel_3534/1624991388.py in <cell line: 1>()
      1 try:
—-> 2     raise ValueError(“元のエラー”)
      3 except ValueError as e:
ValueError: 元のエラー
The above exception was the direct cause of the following exception:
RuntimeError                              Traceback (most recent call last)
/tmp/ipykernel_3534/1624991388.py in <cell line: 1>()
      2     raise ValueError(“元のエラー”)
      3 except ValueError as e:
—-> 4     raise RuntimeError(“新しいエラー”) from e
RuntimeError: 新しいエラー

この例では、ValueErrorが発生した後、RuntimeErrorが発生しますが、fromによって元のエラーも参照されるようになります。

finallyを使った例

try-except構文にはfinallyブロックを追加することも可能で、これは例外が発生したかどうかにかかわらず、必ず実行されます。リソースの解放などに役立ちます。

コピーしました!

python
try:
    with open('non_existent_file.txt', 'r') as f:
        data = f.read()
except FileNotFoundError:
    print("ファイルが見つかりません")
finally:
    print("処理が終了しました")

このコードでは、ファイルが見つからない場合にFileNotFoundErrorをキャッチしつつ、finallyで「処理が終了しました」というメッセージが必ず表示されます。