Python Works

Pythonで色々プログラミングする

Python入門 - 例外処理

例外処理とは何か?

プログラム初心者の方は、「例外処理」と聞いても、何のための処理なのか、何をする処理なのかよくわからないと思います。そこで、まず例外処理について説明しようと思います。

Pythonには、「プログラムの実行中に何かのエラー(例外)が発生した時」に「うまくエラーに対応した処理をするため」、「エラーの発生をキャッチする仕組み」があります。この仕組みを使ってエラー発生時の処理をすることを「例外処理」と呼びます。

例えば、nothing.txtというファイルが存在しない状態で、次のようなプログラムを実行してみましょう。

 

サンプルコード

f = open('nothing.txt', 'r')

 

実行結果

Traceback (most recent call last):
  File "*******.py", line 1, in 
    f = open('nothing.txt', 'r')
FileNotFoundError: [Errno 2] No such file or directory: 'nothing.txt'

 

この「FileNotFoundError」というのは、読んで字のごとく、「ファイルが見つかりませんでした」というエラーです。これは、存在しないnothing.txtを読み込もうとしたがら発生しました。実際にnothing.txtがあるのかないのかは、プログラムをしたタイミングではわかりません。実際にプログラムを実行した時にファイルがあるかどうかが問題だからです。

このような、「プログラム実行時に発生するエラー」に「例外処理」を使って、うまく対応していきます。

 

例外処理の使い方 

さて、それでは例外処理の使い方を説明します。

 

書式 

try:
  例外が発生するかもしれない処理
  例外が発生するかもしれない処理
  ・・・
except 例外のタイプ
  例外が発生した時の処理
  例外が発生した時の処理
  ・・・

 

サンプルコード

try:
    f = open('nothing.txt', 'r')
    print(f.read())
    print('read nothing.txt');
    f.close()
except FileNotFoundError:
    print('error!')

print("=========")

try:
    f = open('readme.txt', 'r')
    print(f.read())
    print('read readme.txt')
    f.close()
except FileNotFoundError:
    print('error!')    

 

実行結果

error!
=========
1st line
2nd line
last line

read readme.txt

 

サンプルのように、例外処理をすると、例外が発生してもプログラムが異常終了することはなくなります。また、例外が発生すると、その後の行は実行されず、すぐにexceptに処理が移ります。

また、例外が発生しないと、exceptブロックの処理は実行されません。

 

複数の例外処理をする

 1つのtryブロックと組み合わせられるexceptブロックは1つだけではありません。例外のタイプによって複数exceptブロックをつけることができます。ファイルの中には、以下のデータが入っているとします。

 

ファイルの中身

10
20
30
fourty
50

 

サンプルコード

try:
    f = open('readme.txt', 'r')
    sum = 0
    
    for line in f:
        sum += int(line.strip())
        print(sum)
        
    print('read readme.txt')
    f.close()
except FileNotFoundError:
    print('file not found!')

except ValueError:
    print("line is not int")

 

実行結果

10
30
60
line is not int

 

このサンプルは、ファイルの中身を読み取って数値に変換して足していくプログラムです。途中までは順調に実行できますが、途中に数値に変換できない文字列が含まれています。これを変換しようとすると「ValueError」が発生します。ValueErrorのexceptブロックのみが実行されているのがわかると思います。

 

ところで、このプログラムには重大な問題があります。それは、tryブロックの途中で例外が発生すると、f.closeが実行されなくなってしまうという問題です。これでは、ファイルが開きっぱなしになってしまいます。

このような状態に対処するために、Pythonにはクリーンアップ処理の仕組みが存在します。

 

クリーンアップ処理

 クリーンアップ処理とはtryブロック内の処理が、エラーが出て終了した場合も、エラーが出ないで終了した場合も、どちらでも必ず実行される処理のことです。終了時に必要なファイルを閉じる処理などを行います。

 

 サンプルコード

import sys

try:
    f = open('readme.txt', 'r')
    
except FileNotFoundError:
    print('file not found!')
    sys.exit(1)

try:
    sum = 0
    
    for line in f:
        sum += int(line.strip())
        print(sum)
        
    print('read readme.txt')
    f.close()
except ValueError:
    print("line is not int")

finally:
    f.close()
    print('clean')

 

実行結果

10
30
60
line is not int
clean

 

 サンプルのようにfinallyブロックをつけるとクリーンアップ処理を実行できます。

 

また、ファイルを開けなかった場合の処理を別に分けたのには理由がります。ファイルを開けなかった、つまり「 f 」にオブジェクトが代入されなかったにもかかわらず、f.closeを実行してしまうとエラーになってしまうためです。