Python × 入門 | #17 エラーをつかまえよう

0-16ではクラスを学びました。今回のテーマは「例外処理」です。プログラムが動いているとき、予期しないエラーが起きるとそのまま止まってしまいます。try/except を使うと、エラーをつかまえてクラッシュを防げます。まず言葉を整理してから、ブロックを順に確認します。

Python × 入門 | #17 エラーをつかまえよう

まずはPycoBlocksを開こう

下のPycoBlocksで直接作業するか、別タブで開き、生成されるPythonコードを見ながら進めてください。

まず用語を整理しよう

例外処理には5つの用語が出てきます。今は「なんとなくそういうものか」程度でかまいません。

用語 読み方 一言で言うと
例外 れいがい プログラム実行中に発生するエラーのこと(exception)
try トライ 「試してみる」ブロック。エラーが起きるかもしれないコードを囲む
except エクセプト エラーが起きたときだけ実行されるブロック
ValueError バリューエラー int("abc") のような「変換できない値」を渡したときのエラー
ZeroDivisionError ゼロディビジョンエラー 0で割り算したときに発生するエラー

ステップ1:エラーをつかまえてみよう

int("abc") を実行すると、"abc" は整数に変換できないので ValueError が発生してプログラムが止まります。try/except を使うと、このエラーをつかまえてプログラムを続けられます。

intro_0-17_a_basic_try

ブロックの動きを整理します。

  1. 「試す:」の中のコードを実行する
  2. エラーが起きなければ、「エラー(...)のとき:」の中はスキップして次へ進む
  3. エラーが起きたら、「エラー(...)のとき:」の中に飛んで処理を実行する
try:
    x = int("abc")
except ValueError:
    print("整数に変換できませんでした")
整数に変換できませんでした

int("abc")ValueError が発生し、except ValueError: ブロックに入ります。エラーが起きなかった場合(例えば int("42"))は except に入らず、x = 42 のまま続きます。

ステップ2:エラーの種類を指定する

ドロップダウンでエラーの種類を選ぶと、そのエラーだけを対象にできます。ZeroDivisionError(0で割ったときのエラー)を指定した例です。

intro_0-17_c_divide
a = 10
b = 0
try:
    print(a / b)
except ZeroDivisionError:
    print("0では割れません")
0では割れません

ドロップダウンには ValueError / ZeroDivisionError / TypeError / IndexError / KeyError / Exception(エラー全般) が用意されています。何のエラーが起きるかわからないときは「エラー全般(Exception)」を選ぶと、どんなエラーもつかまえられます。

ステップ3:エラーの内容を受け取る

「エラーを e ▼ として受け取る:」ブロックを使うと、エラーの詳細を変数に受け取れます。str(e) でエラーメッセージを文字列として表示できるので、何が起きたのか確認できます。

intro_0-17_b_except_as
try:
    x = int("abc")
except Exception as e:
    print("エラー:" + str(e))
エラー:invalid literal for int() with base 10: 'abc'

e にはエラーオブジェクトが入っています。str(e) とすることでエラーの説明文を取り出せます。開発中にデバッグに役立ちます。

コーディングモードで書いてみよう

慣れてきたら、raise を使って自分でエラーを起こすこともできます。入力値が不正なとき、意図的にエラーを発生させてプログラムを止める手法です。

def safe_sqrt(n):
    if n < 0:
        raise ValueError("負の数の平方根は計算できません")
    return n ** 0.5

try:
    print(safe_sqrt(-4))
except ValueError as e:
    print("エラー:" + str(e))
エラー:負の数の平方根は計算できません

raise ValueError("メッセージ") でエラーを発生させ、呼び出し元の except でつかまえています。自分でチェックしたい条件をこの形で書けます。

演習課題

課題17-1:安全に整数変換しよう

変数 text に文字列 "42" を入れておき、int(text) を試してください。変換に成功したら "変換成功:42" と表示し、ValueError が起きたら "整数に変換できませんでした" と表示するプログラムを作りましょう。

詰まったときはこの順で考えてみてください。

  1. 変数に文字列を入れる
    →「変数 text ▼ を "42" にする」で文字列をセットします。
  2. try ブロックに変換と表示を入れる
    →「試す:」の中に「変数 n ▼ を int(text) にする」→「"変換成功:" + str(n) を表示する」をつなぎます。
  3. except ブロックにエラーメッセージを入れる
    →「エラー(ValueError)のとき:」の中に「"整数に変換できませんでした"を表示する」を入れます。
  4. text を "abc" に変えて確認する
    → except 側に入るか確認できます。
▶ 模範解答と解説を見る

ブロックの組み合わせ例:

intro_0-17_ans1_safe_int
text = "42"
try:
    n = int(text)
    print("変換成功:" + str(n))
except ValueError:
    print("整数に変換できませんでした")

解説: "42" は整数に変換できるので try ブロックが最後まで実行され、"変換成功:42" と表示されます。text = "abc" に変えると int("abc")ValueError が起き、except に飛びます。

課題17-2:エラーメッセージを表示しよう

変数 a = 10b = 0 を用意して a / b を試してください。エラーが起きたら変数 e として受け取り、"エラー:" + str(e) を表示するプログラムを作りましょう。

詰まったときはこの順で考えてみてください。

  1. 変数を用意する
    →「変数 a ▼ を 10 にする」→「変数 b ▼ を 0 にする」をつなぎます。
  2. 「エラーを e ▼ として受け取る:」ブロックを使う
    →「試す:」の中に a / b を表示するブロックを入れます。
  3. エラーのとき:の中に表示を入れる
    →「"エラー:" + str(e)▼ を表示する」を入れます。e は文字列に変換(str())が必要です。
▶ 模範解答と解説を見る

ブロックの組み合わせ例:

intro_0-17_ans2_safe_divide
a = 10
b = 0
try:
    print(a / b)
except Exception as e:
    print("エラー:" + str(e))

解説: 10 / 0ZeroDivisionError が発生し、except に入ります。Exception はすべてのエラーをつかまえられるので、エラーの種類を問わず対応できます。str(e)"division by zero" という文字列になります。

課題17-3:リストのIndexErrorをつかまえよう

fruits = ["りんご", "バナナ", "みかん"] のリストを作り、fruits[5](存在しない番号)を取り出してみてください。IndexError をつかまえて "その番号の果物はありません" と表示するプログラムを作りましょう。

詰まったときはこの順で考えてみてください。

  1. リストを作る
    →「空のリスト [ ]」→「リスト fruits ▼ に "りんご" を追加する」を3回繰り返してリストを作ります。
  2. try ブロックにリスト取得と表示を入れる
    →「試す:」の中に「リスト fruits ▼ の 5 番目を表示する」を入れます。
  3. エラー(IndexError)のとき:にメッセージを入れる
    →「"その番号の果物はありません"を表示する」を入れます。
  4. 番号を変えて動作確認する
    → インデックスを 1 にするとエラーなく "バナナ" が表示されます。
▶ 模範解答と解説を見る

ブロックの組み合わせ例:

intro_0-17_ans3_index_error
fruits = []
fruits.append("りんご")
fruits.append("バナナ")
fruits.append("みかん")
try:
    print(fruits[5])
except IndexError:
    print("その番号の果物はありません")

解説: リストの長さは3なので、インデックス5は存在しません。fruits[5] を実行した瞬間に IndexError が発生し、except に飛びます。インデックスを 1 にすると "バナナ" が表示され、except には入りません。

課題17-4:raiseで自分からエラーを起こそう

変数 age = -5 を用意してください。age が0未満のとき raise ValueError("年齢は0以上にしてください") を発生させ、try/except Exception as e: でつかまえてエラーメッセージを表示するプログラムを作りましょう。

詰まったときはこの順で考えてみてください。

  1. 「エラーを e ▼ として受け取る:」ブロックを使う
    → try の中に if と raise を組み合わせます。
  2. try の中に if ブロックを入れる
    →「もし age ▼ < 0 だったら」→「エラーを発生させる(ValueError:"年齢は0以上にしてください")」を入れます。
  3. if のあとに正常時の表示を入れる
    → if ブロックの次(同じ try ブロック内)に「"年齢:" + str(age) を表示する」をつなぎます。age < 0 のときは raise で止まるのでここには来ません。
  4. except の中にエラーメッセージを入れる
    →「"エラー:" + str(e) を表示する」を入れます。
▶ 模範解答と解説を見る

ブロックの組み合わせ例:

intro_0-17_ans4_raise_age
age = -5
try:
    if age < 0:
        raise ValueError("年齢は0以上にしてください")
    print("年齢:" + str(age))
except Exception as e:
    print("エラー:" + str(e))

解説: age = -5 なので if に入り、raise ValueError(...) でエラーを発生させます。raise が実行されると try の残りはスキップされ、except に飛びます。age = 20 に変えると raise されず、"年齢:20" が表示されます。

まとめ

  • try ブロックにエラーが起きるかもしれないコードを書きます
  • except ブロックはエラーが起きたときだけ実行されます。エラーがなければスキップされます
  • ドロップダウンでエラーの種類(ValueErrorZeroDivisionError など)を指定できます
  • except Exception as e: を使うとエラーの詳細を変数に受け取り、str(e) でメッセージを確認できます
  • raise を使うと意図的にエラーを発生させられます。入力値のチェックに役立ちます

次は、文字列をより細かく扱うための「文字列メソッド」を学びます。→ Python × 入門 | #18 文字列を自在に操ろう

PAGE TOP