プログラムを実行していると、ファイルが見つからない、ネットワーク接続が失敗する、ユーザー入力が不正など、さまざまなエラー(例外)が発生します。
これらの例外を適切に処理しないと、プログラムは予期せず終了してしまいます。
本記事では、Pythonの例外処理機能として代表的な try / except / raise / finally の使い方を、初心者向けにシンプルかつわかりやすく解説します。
例外処理の概要
例外とは、プログラムの実行中に想定外の事態(エラー)が発生した際に、「通常の処理の流れ」を中断し、エラー情報を呼び出し元や上位の処理に伝える仕組みを指します。
Pythonでは、例外が発生する可能性のあるコードを try ブロック内に書き、その後の処理を except ブロックで補足します。
例外発生の原因例
- ゼロで割る
- 数値変換で、数字でない文字を指定
- 配列の範囲外にアクセス
- ファイルが存在しない
- 引数が不正
- 未定義の変数を呼び出す
try / except の基本構文
except 例外名: で特定の例外を補足します。
どの例外にもマッチさせたい場合は、except Exception: や bare except: を利用可能ですが、なるべく具体的な例外を指定するのがベストプラクティスです。
try:
# 例外が発生する可能性のある処理
num = int(input("数値を入力してください: "))
result = 10 / num
print(f"10 ÷ {num} = {result}")
except ZeroDivisionError:
# ゼロ除算の例外を補足
print("0では割り算できません。別の数値を入力してください。")
except ValueError:
# 整数変換の例外を補足
print("数値以外が入力されました。整数を入力してください。")
複数の例外をまとめて補足
複数例外をタプルでまとめて指定し、as 変数 で発生した例外オブジェクトを参照できます。
try:
# ファイルを開いて読み込む
with open("data.csv", "r", encoding="utf-8") as f:
data = f.read()
print(data)
except (FileNotFoundError, PermissionError) as e:
print(f"ファイルを開けませんでした: {e}")
raise を使った例外の発生(送出)
独自のエラー条件を検出した際に、自ら例外を発生させるには raise を使います。
def divide(a, b):
if b == 0:
raise ValueError("b に 0 が指定されました。0 以外の値を指定してください。")
return a / b
try:
result = divide(10, 0)
except ValueError as e:
print(f"エラー: {e}")
raise 例外クラス(“メッセージ”) によって例外を送出できます。
except 内での raise の使い方
except ブロック内でも raise を使って再度例外を送出できます。
try:
value = int(input("数値を入力: "))
except ValueError as e:
print("入力が不正です。詳細を表示します。")
# もとの例外をそのまま再送出
raise
単に raise と書くと、キャッチした同じ例外をそのまま呼び出し元へ伝搬します。
raise NewException(“説明メッセージ”) from e のように書くと、元の例外をチェインして別の例外を送出できます。
except Exception: と bare except: の使い方
except Exception: は Exception クラスおよびそのサブクラス(ほとんどの例外)をまとめて補足します。
bare except: はシステム退出用の例外(SystemExit、KeyboardInterrupt)なども含め、すべての例外を捕捉してしまいます。
try:
do_something()
except Exception as e:
# Exception 系の例外のみ捕捉
log_error(e)
except:
# さらに広く、全例外を捕捉(推奨されない)
print("予期せぬエラーが発生しました。")
一般には、予期しないシステム終了を邪魔しないよう except Exception: を使い、bare except: は可能な限り避けるのが望ましいです。
Exception クラス階層と代表的サブクラス
Python の標準例外はすべて BaseException を頂点(スーパークラス)とした階層を持ち、実際の開発で扱うのはその下位にある Exception のサブクラスです。サブクラスの一例を紹介します。
BaseException
└─ Exception
├─ ArithmeticError
│ ├─ ZeroDivisionError
│ └─ OverflowError
├─ LookupError
│ ├─ IndexError
│ └─ KeyError
├─ ValueError
├─ TypeError
├─ IOError (OSError)
├─ FileNotFoundError (OSError)
└─ RuntimeError
ValueError は Exception のサブクラスであり、数値変換の失敗などを表します。
IndexError(シーケンスの範囲外アクセス)、KeyError(辞書にないキー参照)、TypeError(不適切な型操作)、IOError/OSError(入出力エラー)など、多くの例外が Exception を継承しています。
finally の使い方
try~except の後に finally ブロックを置くと、例外の有無にかかわらず必ず実行される後片付け処理を書けます。
try:
f = open("log.txt", "a", encoding="utf-8")
f.write("プログラムを実行しました。\n")
except IOError as e:
print(f"書き込みエラー: {e}")
finally:
f.close()
print("ファイルを閉じました。")
ネットワーク接続の切断やファイルクローズなど、確実に行いたい処理に適しています。
例外処理のベストプラクティス
- 具体的な例外をキャッチ
except Exception: や except: のみを使うと、不具合箇所の特定が難しくなる。 - 例外オブジェクトを利用
as e で取得し、ログ出力やユーザーメッセージに活用。 - 不要な try 範囲は小さく
例外が発生しそうな処理だけを try に含め、どこでエラーが起きたか分かりやすくする。 - リソース管理には with 文を活用
ファイルやネットワークソケットは with open(…) as f: などで自動クローズ。
演習問題
以下の問題に取り組んで、例外処理の理解を深めましょう。
問題1
ユーザーからファイルパスを入力させ、その内容を表示するプログラムを作成してください。
- ファイルが存在しない場合は「ファイルが見つかりません」と表示。
- 読み込みエラーが発生した場合は「ファイルを読み込めませんでした」と表示。
問題2
リスト nums = [5, 0, “a”, 10] の要素を順に取り出し、10を各要素で割るプログラムを書いてください。
- 要素が数値以外(ゼロ除算含む)の場合はスキップし、処理を続行する。
問題3
以下の関数 calculate_score に、引数が 0~100 の範囲外の場合は ValueError を送出するコードを追加してください。
def calculate_score(score):
# ここに範囲チェックの例外送出を追加
return f"スコアは {score} 点です"
演習問題の解答例
解答1
path = input("ファイルパスを入力してください: ")
try:
with open(path, "r", encoding="utf-8") as f:
print(f.read())
except FileNotFoundError:
print("ファイルが見つかりません")
except IOError:
print("ファイルを読み込めませんでした")
解答2
nums = [5, 0, "a", 10]
for x in nums:
try:
result = 10 / x
except ZeroDivisionError:
print(f"{x} はゼロ除算のためスキップします")
continue
except TypeError:
print(f"{x} は数値ではないためスキップします")
continue
print(f"10 ÷ {x} = {result}")
解答3
def calculate_score(score):
if not (0 <= score <= 100):
raise ValueError("score は 0 以上 100 以下で指定してください")
return f"スコアは {score} 点です"
# 使用例
try:
print(calculate_score(120))
except ValueError as e:
print(f"エラー: {e}")
まとめ
本記事では、Pythonの例外処理の基礎である try / except / raise / finally の使い方を、初心者向けに解説しました。
except 内での raise、except Exception: と bare except: の違い、そして Exception クラス階層の理解を深めることで、より堅牢なプログラム設計が可能になります。
演習問題に挑戦し、ぜひご自身のコードへ例外処理を取り入れてみてください!