初めてのPython実践試験学習 第16回「Pythonの言語仕様:例外処理と構文」

こんにちは、吉政創成 菱沼です。

今回もPythonエンジニア育成推進協会のPython 3 エンジニア認定実践試験の主教材「Python実践レシピ/技術評論社」を使って学習中です。

前回は、Blackの補足的な部分として、VS CodeでBlackを使えるようにする設定やオプションについて学び、Black編を終えました。

今回からChapter.3 Pythonの言語仕様の章に入ります。まずはこの章最初の節である例外処理について学びます。

例外と例外処理のキホン。

プログラムを動かしたときに、予期しないエラーの発生によってプログラムが停止し、エラーメッセージが表示されますが、この状態を「例外」と言います。エラーメッセージには、エラーが発生した箇所を含めた情報が含まれています。

ただ、事前にエラーが発生すると想定できる場所に対して適切な処理をしておくことでプログラムを停止させずに処理を継続することができます。この指示を「例外処理」と呼びます。

書籍ではまず0で割ったときのPythonの挙動を例に説明されています。

0で割るという行為は数学的にも定義されておらず、答えは存在しません。Pythonでは0で割ったときには次のような結果が表示されます。

通常であればこうした直球の計算は行わないと思いますが、数字が順番に変数に入れられていくようなプログラムであった場合には、プログラムが停止しないよう、あらかじめ例外処理を定義しておいてあげることでプログラムを止めずに処理を進めてもらうことができます。

—————————

P.40

例外が発生する可能性のある箇所をtry-exceptで囲んで例外を捕捉することで、プログラムが停止するのを防ぐことができます。

exceptキーワードの後ろには、補足したい例外クラスを指定します。上記のコードでは、try節の中で0で除算しているため例外が送出されますが、発生した例外がexceptで指定したZeroDivisionErrorと一致するためexcept節が実行されます。もしexceptで指定された例外と一致しない例外が発生した場合は、その例外はtry節の外側に再送出されます。

—————————

tryには「例外が発生するかもしれない処理」を書き、exceptには想定される例外が発生した時にどういった処理をするかを書くということです。

例外処理で指定していないエラーが発生した場合は、例外処理ができないので、エラーが発生し、プログラムが停止します。

複数の例外を捕捉する方法

ところで、複数のエラーを想定することもあると思います。そうした時にはどうしたらいいでしょうか。

—————————

P.41

複数のexcept節を用いて、発生した例外に応じて処理を分けることもできます。下記の例では、数値を文字列で除算しようとしているので、TypeErrorが発生します。

try:
    num = 10 / ‘2’
except ZeroDivisionError:
    print(‘0で割ることはできません’)
except TypeError:    print(‘文字列で割ることはできません’)

文字列で割ることはできません

—————————

それぞれのエラーに対応する処理をこんな感じで書いてあげるようです。

ちなみに、複数のエラーが出たとしても、処理する内容が同じでいいのであれば、[except (ZeroDivisionError, ValueError)]というように、並列で書いてもいいそうです。

例外が発生した理由を表示させる

ただ、並列で書いてすっきりさせたところで、どのエラーなのかが分からなければ、対処のしようがありません。なので、エラーの内容がなんだったのかを表示させることも可能です。

—————————

P.41

「as 一時変数名」形式で例外オブジェクトを受け取ることができ、except節のなかで利用できます。

try:
    num = 10/ 0
    print(f’除算の結果は {num} になります’)
except (ZeroDivisionError, TypeError, NameError) as e:
    print(f’ Exceptions class; {type(e)}’)
    print(f’ Exceptions occurred; {(e)}’)


 Exceptions class; <class ‘ZeroDivisionError’>
 Exceptions occurred; division by zero

—————————

このサンプルでは二つのメッセージを表示させるようになっています。

print(f’ Exceptions class; {type(e)}’)は、例外の「型(クラス)」で、どの種類のエラーなのかを、

print(f’ Exceptions occurred; {(e)}’)は、例外の「内容(メッセージ)」で、ユーザーや開発者に「何が原因だったか」を具体的に説明する文章になっています。

型の方は開発者向けで、内容の方はユーザーなどの人向けという形だそうで、実務ではどちらかだけでも問題ないようです。

else節を使って例外と成功を区別する

ところで、「例外が発生するかもしれない処理」はtryに書かれますが、例外が発生しなかった場合に実行される処理をelse節として書くこともできるそうです。

先ほどのサンプルでは

try:
    num = 10 / 0
    print(f’除算の結果は {num} になります’)
except ZeroDivisionError:
    print(‘0で割ることはできません’)


    0で割ることはできません

となっており、計算式の次の行にエラー発生しなかった場合の処理が書かれています。

これをelse節として分けると次のように書けるようになるとのこと。else節を書く場合は、すべてのexcept節よりも後ろに置かれます。

—————————

P.41

次の例では、try節の除算が正常に実行された場合のみ結果を表示したいので、else節を使用しています。例外が発生した場合は、else節にあるprint()関数は実行されません。

try:
    num = 10 / 5
except ZeroDivisionError:
    print(‘0で割ることはできません’)
else:
    print(f’除算の結果は {num} になります’)


除算の結果は 2.0 になります

—————————

こう書くと、例外が発生せずに成功したときの処理と、例外が発生したときの処理をはっきり分けられるので、わかりやすいですね。

finally節で例外の有無にかかわらず必ずやっておくことを書く

例えばExcelなどの外部ファイルを使っている場合、エラーが発生しようが、発生しなかろうが、最後には開いたファイルやデータベースは閉じてあげる必要があります。そうしなければファイルがロックされてしまったり、データが正しく保存されなかったりといったことが起きてしまうことがあるためです。

そうした必ずやっておく必要がある処理はfinally節を使って書いておくことになります。

—————————

P.42

下記の例では、ファイルを開いたあとに、存在しない変数dataの中身を書き込もうとして例外が発生しますが、finally節でファイルを閉じることでリソースを確実に開放しています。このように例外が発生してもしなくても必ず実行すべき処理をfinally節に書くとよいでしょう。

f = None
try:
    f = open(‘python.txt’, mode=’w’)
    f.write(data)
finally:
    if f:
        f.close()
        print(‘ファイルを閉じました’)

        
ファイルを閉じました
Traceback (most recent call last):
  File “<pyshell#44>”, line 3, in <module>
    f.write(data)
NameError: name ‘data’ is not defined

—————————

[f = open(‘python.txt’, mode=’w’)]の部分はファイルを書き込みモードで開く部分です。
開かれたファイルに対してdataを書き込むという処理を行いますが、ここでは例外が発生する可能性があります。そこでfinally節で、どんな状況であってもファイルを閉じるという処理が書かれています。

例外処理と関連して、ファイルを開く部分を[with open(‘python.txt’, mode=’w’) as f:]というようにwith文を使って書いてあげることもできるそうです。finallyをうっかり書き忘れたとしてもリソースを安全に開放してくれるwith文を書いておくことで、Pythonが自動で閉じるという作業をしてくれるのだとか。短くするという利点もありますね。

例外処理の構文まとめ

例外処理について、try、except、else、finallyの使い方について学びましたが、これには書く順番があります。また、tryの後にはexcept節かfinally節のどちらかを置く必要があるとのこと。

以下、テキストからの引用です。この順番で書くというルールになっています。

try:
    例外が発生する可能性のある処理
except 捕捉したい例外クラス:
    例外が発生したときの処理
else:
    try節で例外が発生しなかった場合のみ実行される処理
finally:
    例外の発生産むに関わらず必ず実行される処理

それではきりが良いので、今回はこちらで終了です。お付き合いいただきありがとうございました。

実践試験について知りたい方は以下をご覧ください。

●Python3エンジニア認定実践試験

PAGE TOP