⚠️ 記事内に広告を含みます。

pythonの例外処理

例外処理はエラー発生しても途中でプログラムが止まらないようにする処理のこと

例外処理とは?

pythonのプログラムは、プログラムの途中でエラーが発生すると停止します。

例えば以下のプログラムでは定義していないaは表示できないのでエラーが発生して、1+2は実行されずに終了します。

print(a)
print(1+2)

---実行結果---
NameError:

しかし、事前に想定されるエラーも中にはあるのに、プログラム中でエラーが発生して停止すると困りますよね?

想定のエラーは例外と呼び、想定内のエラーが起きたときには指定した処理を実行するのが「例外処理」です。

例外の例

想定されるエラーとは、例えばユーザからの入力値を変数に代入する例で発生します。

以下の例を見てみましょう

def no_exception():
    a = int(input("何人前のパスタをつくりますか?"))
    print("ゆでるパスタは" + str(a*100) + "gです。")
    print("一人当たり" + str(420/a) + "円です。")
def no_exception()

ここでユーザが意図通りに10と入力してくれると以下の結果が得られます。

何人前のパスタをつくりますか?10
ゆでるパスタは1000gです。
一人当たり42.0円です。

しかし、ユーザが適当にエンターを押して値を何も入力しないとエラーが発生して止まります。

ValueError: invalid literal for int() with base 10: ''

ユーザが正しく入力しないことは想定されるのでエラー発生で停止しなように例外処理を書きます。

tryとexceptで例外処理を書く

例外処理が発生する処理をtryに、例外が発生したときにする処理をexcept:に書きます。

def main():
    try:
        a = int(input("何人前のパスタをつくりますか?"))
        #パスタは1人前が100gで、aの値を書けたグラム数を計算する
        print("ゆでるパスタは" + str(a*100) + "gです。")
        #一袋420円のパスタを人数aで割り勘する
        print("一人当たり" + str(420/a) + "円です。")

    except ZeroDivisionError:
        print("0で割ることはできません,0以外の数字を入力してください")
    except ValueError:
        print("何人分のパスタを作るか数字を入力してください")
    except:
        print("エラーが発生しました")

main()

ここで想定されるエラー・例外は2つあります。

  • ユーザが0を入力 →ゼロ除算(ZeroDivisionError)
  • ユーザが数字以外を入力、または空でエンター → ValueError

try: の部分には通常通りの処理をいれます。
Except:の部分にはexcept エラー名: 実行する処理を記述します。
※エラー名は実際に実行してエラーを起こして見ると分かる

上記のプログラムはユーザが0または0以外の数字を入力した場合に対応する文字を表示、それ以外のエラーが発生した場合は「エラーが発生しました」が出力されて、プログラムが停止しないようになります。

---0を入力--
何人前のパスタをつくりますか?0
ゆでるパスタは0gです。
0で割ることはできません

--何も入力しない---
何人前のパスタをつくりますか?
何人分のパスタを作るか数字を入力してください

もしもエラーが発生しても何もしなくて良い場合はpassと書きます。例えば0と入力された場合は茹でるパスタの量も割り勘金額も必要ないので何も出力の必要がないのでpassでも良いかもしれません

def main_pass():
    try:
        a = int(input("何人前のパスタをつくりますか?"))
        #パスタは1人前が100gで、aの値を書けたグラム数を計算する
        print("ゆでるパスタは" + str(a*100) + "gです。")
        #一袋420円のパスタを人数aで割り勘する
        print("一人当たり" + str(420/a) + "円です。")

    except ZeroDivisionError as err: 
        pass # 何もしない

main_pass()

as でエラー内容を変数に入れる

exceptのエラー名のあとにas 変数名:を記述すると、その変数にエラー名を代入することができます。

except ZeroDivisionError as err: errに変数名を入力

def mainas():
    try:
        a = int(input("何人前のパスタをつくりますか?"))
        #パスタは1人前が100gで、aの値を書けたグラム数を計算する
        print("ゆでるパスタは" + str(a*100) + "gです。")
        #一袋420円のパスタを人数aで割り勘する
        print("一人当たり" + str(420/a) + "円です。")

    except ZeroDivisionError as err: 
        print("0で割ることはできません")
        print(err)
    except ValueError:
        print("何人分のパスタを作るか数字を入力してください")
    except:         #エラー名が書いてないので全てのエラーと言う意味になる
        print("エラーが発生しました")
        

mainas()

print(err)としているので、0を入力した場合はdivision by zeroのエラー名が出力されている。

何人前のパスタをつくりますか?0
ゆでるパスタは0gです。
0で割ることはできません
division by zero

finallyはエラーが発生しなくても実施した処理を書く

exceptはその例外が発生した場合のみに実行されます。
finallyという文もあり、finallyの記述はエラーが発生しなくても最終的に個々に記述した処理が実行されるようにかけます。

def main_finally():
    try:
        a = int(input("何人前のパスタをつくりますか?"))
        #パスタは1人前が100gで、aの値を書けたグラム数を計算する
        print("ゆでるパスタは" + str(a*100) + "gです。")
        #一袋420円のパスタを人数aで割り勘する
        print("一人当たり" + str(420/a) + "円です。")

    except ZeroDivisionError as err: 
        print("0で割ることはできません")
        print(err)
    except ValueError:
        print("何人分のパスタを作るか数字を入力してください")
    except:
        print("エラーが発生しました")
    finally:
        print("処理が終了しました")

main_finally()

finally: の処理はエラーが出てもでなくても処理される。

何人前のパスタをつくりますか?10
ゆでるパスタは1000gです。
一人当たり42.0円です。
処理が終了しました

エラーが発生してもしなくてもfinallyの処理が実行されるならtryの部分に書いてもよい気もしますが、tryの部分の処理はあくまでエラーが発生しなかった場合の処理で、エラーが発生したらexceptの処理が実行されます。

tryの処理が完了したことを明示するためのひとこと「処理完了」と書いたり、
この処理の過程で開いていたファイルを閉じるというときにも使えます。

csv_file = open("test.csv", "w")

def main():
    try:
        csv_file.write("test csv files ")
    except:
        ~~~~~
    finally:
        csv_file.close()  #test.csvはエラーが発生してもしなくても開いているので閉じる。

#openで開いたファイルは閉じておかないとエラーや不具合の原因になる可能性がある。

elseはexceptが発生しなかったときに実行される処理

ifのelseのようにexceptに対してelseもあります。
下記の例ではelse::の処理は例外が発生しなかったときに実行されます。

def main_finally():
    try:
        a = int(input("何人前のパスタをつくりますか?"))
        #パスタは1人前が100gで、aの値を書けたグラム数を計算する
        print("ゆでるパスタは" + str(a*100) + "gです。")
        #一袋420円のパスタを人数aで割り勘する
        print("一人当たり" + str(420/a) + "円です。")

    except ZeroDivisionError as err: 
        print("0で割ることはできません")
        print(err)
    except ValueError:
        print("何人分のパスタを作るか数字を入力してください")
    except:
        print("エラーが発生しました")
    else:
        print("例外は発生しませんでした")
        
    finally:
        print("処理が終了しました")
   
main_finally()

try文中にraiseを入れてエラー発生のテストもできる

raiseのあとにエラー名を入力してエラーを人工的に発生可能

def main_pass():
    try:
        raise ValueError("エラーを発生させました") #raiseでエラーを発生させる
        a = int(input("何人前のパスタをつくりますか?"))
        #パスタは1人前が100gで、aの値を書けたグラム数を計算する
        print("ゆでるパスタは" + str(a*100) + "gです。")
        #一袋420円のパスタを人数aで割り勘する
        print("一人当たり" + str(420/a) + "円です。")
    except ZeroDivisionError as err: 
        pass # 何もしない

    except ValueError:
        print("何人分のパスタを作るか数字を入力してください")

main_pass()
何人分のパスタを作るか数字を入力してください
処理が終了しました

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です