Pythonの例外処理

Python の例外は、プログラムの実行時に発生する重要なイベント、通常はエラーを通知するために使用される構造体です。

例外が適切に “捕捉” (つまり正しく処理) されないと、プログラムが停止してしまうかもしれません。

もし、あなたのプログラムが実行されたときに例外を発生させるかもしれないと思ったら、次のセクションで紹介する try/except を使って例外を処理すると便利でしょう。

>
このガイドでは、Python の例外とは何か、最も一般的な例外の種類、そして発生した例外を try 節と except 節を使ってどのように処理するかについて紹介します。

例外の処理

以下の例では、ユーザーに数値の入力を促し、実行後、与えられた数値の2乗の値を出すプログラムです。

このプログラムは、入力として数字を入力する限り、動作します。

while True:
    x = int(raw_input("Please enter a number: "))
    print("%s squared is %s" % (x, x**2))


文字列や “one “のような数字でない文字を入力すると、プログラムは “Value Error “という例外を発生させます。

$ python squared.py 
Please enter a number: 3
3 squared is 9
Please enter a number: 4
4 squared is 16
Please enter a number: five
Traceback (most recent call last):
  File "squared.py", line 4, in <module>
    x = int(raw_input("Please enter a number: "))
ValueError: invalid literal for int() with base 10: 'five'


ここで例外処理の出番です。

例外を適切に処理する方法を知っておく必要があります。

特に実稼働環境では、例外を処理しないとプログラムが何をすべきかわからなくなり、クラッシュしてしまうからです。

上記のエラーをどのように処理するか見てみましょう。

これは、例外が発生しそうなプログラムを try キーワードで囲み、それに続く except キーワードをマッチさせて、例外が発生した場合に実行することで実現できます。

同じプログラムを書き直してみましょう。

今度は、例外が発生する可能性がある場合に対処するようにします。

while True:
    try:
        x = int(raw_input("Please enter a number: "))
        print("%s squared is %s" % (x, x**2))
    except ValueError:
        print("Please enter a valid number!")


上のプログラムからわかるように、try文の中のコードが最初に実行されます。

エラーが発生しなければ、残りのコードが実行され、 except ステートメントはスキップされます。

例外が発生した場合(数字の代わりに文字列を入力した場合など)、プログラムは try 文にマッチした except 文を実行し、次に try/except ブロックの外側の残りのコード(ある場合)を実行します。

try/except` 文を含むコードを実行すると何が起こるか見てみましょう。

$ python safe_squared.py 
Please enter a number: 3
3 squared is 9
Please enter a number: 4
4 squared is 16
Please enter a number: five
Please enter a valid number!
Please enter a number: 5
5 squared is 25


注意: 複数の try/except 節ハンドラがあったとしても、 except 節は対応する try 節からの例外のみを処理することに注意してください。

Pythonの例外の種類

Pythonにはいくつかの組み込み例外があります。

最も一般的な例外のいくつかを見て、それらが何であり、どのように使用するかの見通しを得ることができるようにしましょう。

KeyError Exception

T

IndentationError Exception

この種の例外は、コードが適切にインデントされていない場合に発生します。

Python は中括弧を使ってスコープを指定する代わりに、インデントを使います。

したがって、インデントを正しく行うことが重要であり、それがこの例外の目的です。

ある数字が偶数かどうかをチェックする関数を書いてみましょう。

def authenticate_user(request):
    try:
        email = request.data['username']
        password = request.data['password']


user = authenticate(email=email, password=password)


if user and user.is_active:
            return Response(user_details,status=HTTP_200_OK)
        else:
            res = {'error': 'can not authenticate with the given credentials'}
            return Response(res, status=status.HTTP_400_BAD_REQUEST)
    except KeyError:
        res = {'error': 'please provide a username and a password'}


この関数は、2 行目と 4 行目の両方でインデントエラーとなります。

なぜなら、この関数はコードが 4 ではなく 8 のスペースでインデントされることを想定しているからです。

このプログラムを実行すると、次のような出力が得られます。

def is_even(number):
    if number % 2 == 0:
    print(" %s is an even number" % (number))
    else:
    print("%s is an odd number" % (number))


print(is_even(1))
print(is_even(2))


SyntaxError Exception

これはPythonで最も一般的な例外の種類の1つです。

コードの構文に間違いがある場合に発生します。

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

$ python is_even.py 
  File "is_even.py", line 3
    print(" %s is an even number" % (number))
        ^
IndentationError: expected an indented block


このコードの出力は、”it’s odd” という文字列が引用符で囲まれていないため、3行目で構文が無効となります。

def is_odd(n):
    if n % 2 != 0:
        print(it's odd)
    else:
        print("not odd")


print(is_odd(7))


構文エラーにはさまざまな種類があり、これはほんの一例に過ぎないことを覚えておいてください。

TypeError Exception

この例外は、指定されたデータ型に対して無効な操作や関数を実行しようとしたときに発生します。

以下の例では、関数 sum_of_numbers は 2 つの引数を受け取り、それらを足し算します。

この関数を 3 つの引数で呼び出そうとすると、2 つの引数のみを想定しているため、TypeError 例外が発生します。

$ python is_odd.py 
  File "is_odd.py", line 3
    print(it's odd)
                  ^
SyntaxError: EOL while scanning string literal


このコードを実行すると、次のような結果になります。

def sum_of_numbers(a, b):
    return a + b


print(sum_of_numbers(1, 2, 7))


Try/except、else、finally句について

例外処理には他にもいくつかの要素があり、それが else 節と finally 節です。

私たちはすでに try 文と catch 文を使うことができ、これらはエラーをキャッチするために使われます。

ここでは、else文とfinally文についても見てみましょう。

その他

else節は、プログラムが例外を発生させなかったときにコードを実行するために使用されます。

また、try節にコードを追加するよりも、else節を使用したほうがよいでしょう。

これは、try/except文で保護されているコードで発生しなかった例外を、意図せずキャッチしてしまうことを避けるためです。

このチュートリアルの最初に使った例を考えてみましょう。

しかし、その代わりに else 文の中で print 文を実行することにします。

$ python sum_of_numbers.py 
Traceback (most recent call last):
  File "sum_of_numbers.py", line 4, in <module>
    print(sum_of_numbers(1, 2, 7))
TypeError: sum_of_numbers() takes exactly 2 arguments (3 given)


このコードを実行すると、エラーが起こりやすい int(raw_input(...)) コードが try 文に、「安全な」コードが else 文に分離されることを除いて、前と同じ機能が提供されます。

while True:
    try:
        x = int(raw_input("Please enter a number: "))
    except ValueError:
        print("Please enter a valid number!")
    else:
        print("%s squared is %s" % (x, x**2))


♪やっとこさ ♪やっとこさ

この節は、例外が発生したかどうかに関係なく実行されなければならないクリーンアップのアクションを定義するためのものです。

finally節は、例外が発生したかどうかに関わらず、常にtry/except` 文を抜ける前に実行されなければなりません。

これは通常、開いているファイルを閉じるなど、後始末をするために使用されます。

この例では、finally節を含めてみましょう。

$ python else_squared.py 
Please enter a number: 3
3 squared is 9
Please enter a number: 4
4 squared is 16
Please enter a number: five
Please enter a valid number!
Please enter a number: 5
5 squared is 25


このコードを実行すると、例外が発生したかどうかに関係なく、ループが何回実行されたかを見ることができることを除けば、前と同じように実行できます。

count = 0


while True:
    try:
        x = int(raw_input("Please enter a number: "))
    except ValueError:
        print("Please enter a valid number!")
    else:
        print("%s squared is %s" % (x, x**2))
    finally:
        print("Ran %s time(s)" % count)


結論

このガイドでは、 try/except 文を使用して Python で例外を処理する方法を、オプションの構成要素である elsefinally を含めて簡単に説明しました。

このチュートリアルで、Pythonの例外処理に関する混乱が解消されれば幸いです。

もっと学びたいのであれば、Pythonドキュメントの Errors and Exceptions のセクションでより多くの情報を得ることができます。

</module

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