[Python基礎]例外処理

Python
スポンサーリンク

例外処理について

プログラムにおいて、コードの文法や式の書き方が正しくてもエラーが発生する可能性があります。これを例外といいます。その例外が発生したときに、適宜処理をするために例外処理というものが用いられます。

例外とエラー結局同じなんじゃないの?と思う方もいるかと思いますが、ニュアンスがちょっと違います。線引きが曖昧で定義の区別が非常に難しいのですが自分の解釈は、Pythonにおいて

想定内の異常が例外、想定外の異常がエラー

という感じです。

通常、プログラム内でエラーが発生すると、強制終了されてしまいます。システムにおいて、強制終了はあまり良くないものです。そこで想定しえるエラーを例外処理として書くことで、例外が観測できるようになりますので結果、エラーが発生しても適宜処理し、プログラムを正常に終了させることが出来ます。

では実装について解説します。

例外処理を実装する

tryとexcept

例外処理はtryとexceptのふたつを用いることで実現できます。

こちらのコードを例に例外処理を実装します。

x = 0
print(1 / x)

ゼロで割ってしまっているので、出力結果は発散してしまいます。

実行してみると以下のようなエラーを伝える文が出力され、単なるエラーとして終了してしまいます。

先ほどのコードに例外処理を加えてみましょう。

try:
    x = 0
    print(1 / x)
except:
    print("Error")

try(試す)節の中に処理する内容を書きます。処理の中にエラーがあると、except(例外)節が実行されます。実行してみると Error と表示されます。エラーを例外処理として扱われ、プログラムが正常終了しました。


正常終了させる分には良いのですが、実際にソフトウェアが完成し早速実行した時、エラーが検出されたら何が原因なのか知る必要があります。

except: だけだと例外処理は可能ですが、具体的なエラーを知ることが出来ません。いわゆる”ワイルドカードのexcept節”です。全てのエラーを観測できるけれど詳細は分からないんですね。

踏まえて次は、エラーを観測しつつエラーの詳細を知ることが出来るExceptionについて解説します。

except Exception

except の後にExceptionを加えることでエラーの詳細を知ることが出来ます。正確には

 except Exception as 変数:

と書くことで例外オブジェクト(エラーの詳細)が変数に格納されます。なおこの変数の名前は特に決まりはありませんが、”err”や”e”と書くのがオーソドックスです。

先ほどのコードにExceptionを追加してみましょう。

try:
    x = 0
    print(1 / x)
except Exception as err:
    print("Error")
    print(err) #errに格納されたエラーの詳細が表示される

実行結果は以下のようになります。エラーの詳細が表示されました。

Error
division by zero

ちなみにコード内のxに代入する値を”a”(str型)に変更すると実行結果がこのようになります。型が違う旨のことが表示されます。

Error
unsupported operand type(s) for /: 'int' and 'str'

Exceptionはとても便利なのですが、想定外の例外まで拾ってしまう可能性もあるため、出来るだけ想定される例外オブジェクトを指定した方が良いようです。


例外オブジェクトの指定について解説します。

例外オブジェクトの指定

先ほど出てきたExceptionの正体とは、システム終了以外の全ての例外を網羅したクラスなんです。いわゆる基底クラスの一種です。

つまり、このExceptionの配下に様々な例外オブジェクトが在るということになります。先ほどのexceptはこの基底クラスを指定していました。

対してこの節では、Exceptionの配下にある例外オブジェクトをexceptで指定するという内容になります。(具体的な指定)

except 例外オブジェクト as 変数:

で実装できます。

では、ここでも1/xのコードで考えてみましょう。

xに代入される値について、発散エラーや変数型エラーを想定する場合、以下のようなコードを書きます。

try:
    x = 0 #この変数を色々変えてみて下さい ex)0、文字列、普通の数
    print(1 / x)
except ZeroDivisionError as err:
    print("Division Error") #発散エラー
    print(err)
    print(type(err)) #オブジェクトの型の確認
except TypeError as err: #型のエラー
    print("TypeError")
    print(err)
    print(type(err))

発散エラーではZeroDivisionErrorクラスを、変数型エラーはTypeErrorクラスをexceptの後に追記します。errには例外オブジェクトが格納されます。

上のコードのコメントアウトのようにxに色々な値を代入して実験してみて下さい。


他にも様々な例外クラスが存在します。参考としてPython公式サイトで紹介されている例外の階層を掲載してみました。こちらのページでそれぞれの例外クラスの詳細が分かります。

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StopAsyncIteration
      +-- ArithmeticError
      |    +-- FloatingPointError
      |    +-- OverflowError
      |    +-- ZeroDivisionError
      +-- AssertionError
      +-- AttributeError
      +-- BufferError
      +-- EOFError
      +-- ImportError
      |    +-- ModuleNotFoundError
      +-- LookupError
      |    +-- IndexError
      |    +-- KeyError
      +-- MemoryError
      +-- NameError
      |    +-- UnboundLocalError
      +-- OSError
      |    +-- BlockingIOError
      |    +-- ChildProcessError
      |    +-- ConnectionError
      |    |    +-- BrokenPipeError
      |    |    +-- ConnectionAbortedError
      |    |    +-- ConnectionRefusedError
      |    |    +-- ConnectionResetError
      |    +-- FileExistsError
      |    +-- FileNotFoundError
      |    +-- InterruptedError
      |    +-- IsADirectoryError
      |    +-- NotADirectoryError
      |    +-- PermissionError
      |    +-- ProcessLookupError
      |    +-- TimeoutError
      +-- ReferenceError
      +-- RuntimeError
      |    +-- NotImplementedError
      |    +-- RecursionError
      +-- SyntaxError
      |    +-- IndentationError
      |         +-- TabError
      +-- SystemError
      +-- TypeError
      +-- ValueError
      |    +-- UnicodeError
      |         +-- UnicodeDecodeError
      |         +-- UnicodeEncodeError
      |         +-- UnicodeTranslateError
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarning
           +-- ImportWarning
           +-- UnicodeWarning
           +-- BytesWarning
           +-- ResourceWarning

例外処理で便利な節① else

例外が発生せず、正常に処理されたときにelse節の内容が実行されます。

try:
    x = 1
    print(1 / x)
except ZeroDivisionError as err:
    print("Division Error")
    print(err)
    print(type(err))
except TypeError as err:
    print("TypeError")
    print(err)
    print(type(err))
else: 正常に処理されたときのみ実行される
    print("No Error")

例外処理で便利な節② finally

finally節では、例外あるなし関わらず必ず実行されます。

try:
    x = 1
    print(1 / x)
except ZeroDivisionError as err:
    print("Division Error")
    print(err)
    print(type(err))
except TypeError as err:
    print("TypeError")
    print(err)
    print(type(err))
else:
    print("No Error")
finally: #例外関わらず必ず出力される
    print("FINISH")

まとめのソースコード

雑ですが、今回説明した例外処理について全パターンをまとめたソースコードです。

#例外処理について
#基本はtryとexceptがセット

if __name__ == "__main__":
    try:
        x = 0 #この変数を色々変えてみて下さい ex)0、文字列、普通の数など
        print(1 / x) #1/0=Div

    except ZeroDivisionError as err: #except 例外オブジェクト as 変数:と書くことで例外オブジェクトを格納できる #当然except 例外オブジェクト:でも可能
        print("Division Error") #発散エラー
        print(err)
        print(type(err)) #オブジェクトの型の確認

    except TypeError as err: #型のエラー
        print("TypeError")
        print(err)

    else: #例外が無かった際に出力される
        print("No Error")

    finally: #例外関わらず必ず出力されるもの
        print("FINISH")


    try:
        print("\nここからはワイルドカードによるエラー観測")
        x = "a"
        print(1 / x)
    except: #exceptだけで書くことで特定の例外のみならずすべての例外を観測できる "ワイルドカードのexcept節"、"bare except"と呼ばれる
        print("Error") #欠点としては、例外オブジェクトを取得できないのでどんなエラーなのか分からない


    try:
        print("\nここからはExceptionによるエラー観測")
        x = 0
        print(1 / x)
    except Exception as err: #except:と違って例外オブジェクトを取得できる が想定外の例外を拾ってしまう可能性あり
        print("Error")
        print(err)
マスルキン

当ブログ管理人のマスルキンです。

高専電気系学科に5年間在籍。卒業後は専攻科に進学し現在に至る。

生まれつき聴覚障害があり
補聴器の使用、コミュニケーションでは読唇や手話などを用いています。

当ブログでは
・プログラミング・研究関係の備忘録
・趣味(筋トレ、カメラ、プラモデル、etc...)
・自身の日常
などを自由気ままに皆様に発信いたします。

記事が皆様のお役に立てば幸いです。

マスルキンをフォローする
Python プログラミング
スポンサーリンク
マスルキンをフォローする
マスルキンの部屋

コメント

タイトルとURLをコピーしました