Pythonのtry except finallyで例外発生の有無を問わず行う処理を書く

ここではPythonの例外処理(try文except節)のオプションであるfinally節について、詳しくかつ簡潔に解説します。

ページ内で解説していますが、これは動作上は、あってもなくても違いはありません。ただし、第三者から見て分かりやすいコードを書くためには、非常に有用です。ここでは、そうした「分かりやすいコードとは何か」にも触れながら解説していきます。

try文とexceptの基本
基本的なtry文exceptについては、「Pythonのtry文とexceptによる例外処理の方法」で詳細に解説しています。そもそもの try except について復習しておきたい方はこちらからご覧ください。
目次

1. try文のfinallyとは

try文の中でfinallyは、「例外が発生したとしても発生しなかったとしても実行したい処理」を書くために使います。

書き方は次の通りです。

In [ ]:
try:
    処理文
except:
    処理文
finally:
    処理文

下図をご覧頂くと流れを理解しやすいと思います。

例を見てみましょう。

In [1]:
try:
    num = '1' + 1
except TypeError:
    print('TypeErrorです。')
finally:
    print('try文を終了します。')
TypeErrorです。
try文を終了します。

このように、例外が発生しなかった場合は、そのままfinallyブロックに書いた処理を実行して終了します。例外が発生した場合は、まずexceptブロックに書いた例外処理を行い、その後にfinallyブロックの処理を実行して終了します。

実は、try文を終了した直後に処理文を書いておけば、わざわざfinally文を使わなくても同じ出力結果になります。ちょうど、下図のようなフローですね。

以下が実際のコードです。

In [2]:
try:
    num = '1' + 1
except TypeError:
    print('TypeErrorです。')

print('try文を終了します。')
TypeErrorです。
try文を終了します。

ただし、finallyを使うと、第三者に対して、その処理がtry文の中で行いたい処理であることを明確に示すことができます。

特に、exceptブロックで複数の例外処理を書いて、try文全体が長くなっているような時は、finallyがあるかないかで、コードの見やすさは大きく異なります。開発において、「誰から見ても分かりやすいコードを書く」という意識はとても重要なので覚えておきましょう。

2. try文のfinallyとelseの組み合わせ

次に、finallyとelseを組み合わせたコードを見てみましょう。この2つを組み合わせると、次のようなフローになります。

このように、tryブロックの処理で例外が発生しなかった場合はelseブロックの処理とfinallyブロックの処理が実行されます。例外が発生した場合はexceptブロックの処理とfinallyブロックの処理が実行されます。

参考までにサンプルコードを書いておきます。まずは、finallyだけの場合です。

In [1]:
sum = 10000

for i in range(3):
    num = input('数値を入力してください。')
    try:
        value = round(sum/int(num))
        print(f'一人当たり{value}円です。')
    except ZeroDivisionError:
        print('0以外の数値を入力してください。')
    except ValueError:
        print('値の型が異なります。')
    finally:
        print('計算を終了します。\n')
数値を入力してください。4
一人当たり2500円です。
計算を終了します。

数値を入力してください。0
0以外の数値を入力してください。
計算を終了します。

数値を入力してください。五
値の型が異なります。
計算を終了します。

このコードは下図のような処理経路になっています。なおfor文については、「Pythonのfor文による繰り返し処理(forループ)の基本」をご覧ください。

これにelseブロックを追加して、例外が発生しなかった場合の処理を書いたものが次のコードです。

In [2]:
sum = 10000

for i in range(3):
    num = input('数値を入力してください。')
    try:
        value = round(sum/int(num))
        print(f'一人当たり{value}円です。')
    except ZeroDivisionError:
        print('0以外の数値を入力してください。')
    except ValueError:
        print('値の型が異なります。')
    else:
        discount = round(value*0.9)
        print(f'割引券をお持ちなので1割引の{discount}円になります。')
    finally:
        print('計算を終了します。\n')
数値を入力してください。4
一人当たり2500円です。
割引券をお持ちなので1割引の2250円になります。
計算を終了します。

数値を入力してください。0
0以外の数値を入力してください。
計算を終了します。

数値を入力してください。五
値の型が異なります。
計算を終了します。

例外が発生しなかった場合のみ、elseブロックの処理が実行されているのが分かりますね。また、コードが長くなればなるほどfinally節があることによって、それがtry文の中で実行したい処理であることを明示するという点の重要性が増していることも実感できると思います。

さて、このコードの処理経路は下図のようになっています。try分の中にelseブロックが追加されている点が、先ほどの図と異なります。

このように、finallyブロックで例外が発生してもしなくても行う処理、elseブロックで例外が発生しなかった場合の処理を追加すると、様々な操作ができますので、ぜひ使いこなせるようになりましょう。

3. まとめ

まとめると、try文のfinally節は、「例外が発生したとしても発生しなかったとしても実行したい処理」を書くためのものです。finally節を利用しなくても、try文を抜けた直後に同じ処理を書いておけば、同じ出力結果を得ることはできます。

しかし、finally節を使うことで、その処理がtry文の中で実行したい処理であることを第三者に対して明確に示すことができます。特にコードが複雑になればなるほど、このメリットの大きさが増大します。まずは「第三者から見てわかりやすいコードを書く」という点において、finally節を活用するようにしましょう。



よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメント一覧 (1件)

  • 「finally節を利用しなくても、try文を抜けた直後に同じ処理を書いておけば、同じ出力結果を得ることはできます」「finally節を使うことで、その処理がtry文の中で実行したい処理であることを第三者に対して明確に示すことができます」

    ちょっと的外れだと思う。

    finally は except の中に return や raise を書いたとき、それらが実行される前に finally の中が実行されることに意義がある。

コメントする

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

目次
閉じる