Python入門
第18回.例外処理(try文)とexception一覧

Pythonの初心者向け入門解説、人気のプログラミング言語Python
最終更新日:2020-09-23

第18回.例外処理(try文)とexception一覧


Python 例外処理 try except

スクリプトを実行したときには各種の例外(エラー)が発生することがあります。
スクリプトを書いて実行し、エラーが出れば修正してまた実行する。
これを繰り返すことでエラーのないプログラムが完成していきます。


しかし、エラーが出ないように完全に対処することは極めて困難です。
それは、プログラムの動作環境(データや外部環境)がその時々で変わるため、これらを完全には考慮しきれないからです。

Pythonは例外(エラー)発生を検知すると、トレースバックを出力しプログラムの実行を強制終了します。
しかし大抵の場合は強制終了されては困るものです。
Pythonには例外発生時に強制終了させずに例外を検知する手段としてtry文が用意されています。


目次

例外処理とは

Pythonは例外発生を検知すると、トレースバックを出力しプログラムの実行を強制終了します。
構文エラーつまり文法エラー(Syntax Error)については、エラーの補足はできません。

def substr3(s):
    """文字列の3文字目を返す
    :param s: 入力文字列
    :return: sの3文字め
    """
    return s[2]
lang = ("Python","VBA","GAS","C","C##")
for s in lang:
    print(substr3(s))
上記のスクリプトを実行するとエラーが発生します。

例外(エラー)発生時の画面

Visual Studioの画面
Python 例外処理 try except

続行すると、

Python 例外処理 try except

さらに続行すると、

Python 例外処理 try except

IDLEの画面
Python 例外処理 try except

デバッグについて

トレースバックにはデバッグに必要な情報が出ています。
上記を見ると、

IndexError: string index out of range

文字列のインデックスが範囲外になっていることが分かります。

print(substr3(s))

return s[2]

このような順番で実行されたことも分かります。
print(substr3(s))これで呼ばれた関数substr3の中で、
return s[2]ここでインデックスが範囲外になったことが分かります。
引数の文字列を確認して、適切な対処する必要があります。

例えば関数作成時には、どのような引数が渡されてくるか考慮しきれない場合があります。
そのような場合でもスクリプトが強制終了されることなく処理を続けるためにtry文がPythonには用意されています。
※もちろん上記の場合は文字列長を判定して何らかの対処をしたほうが良いです。

try文の文法をみた上で、実際にスクリプトにtry文を組み込んでエラーを捕捉していきます。


try文の文法

ひとまとめの文に対して、例外処理および/またはクリーンアップコードを指定します。
公式ドキュメント - 8.4. try 文

try文の構文

try:
    例外が発生するかもしれない処理
except 捕捉する例外ハンドラ as 識別子:
    発生した例外に対する処理
else:
    例外が発生しなかった場合の処理
finally:
    例外発生の有無に関わらず実行する処理

except節

少なくとも1つ以上のexcept節を指定します。
複数のexcept節を記述できます。
例外が発生すると、except節を上から逐次、発生した例外に対応するまで調べます。

例外ハンドラを省略したexceptは最後に書かなければならず、これは全ての例外に対応します。

例外ハンドラが書かれたexcept節に対しては式が評価され、結果のオブジェクトが指定した例外と互換である場合にその節が対応します。

例外がどのexcept節にも合致しなかった場合、現在のコードを囲うさらに外側、そして呼び出しスタックへと検索を続けます。
いずれのexcept節にも合致しなかった場合は、例外発生によって実行は強制終了されます。

複数の例外ハンドラに対して同一の処理を行う場合は、()括弧の中に,カンマ区切りで複数の例外ハンドラを列挙します。

as 識別子
except節内で例外オブジェクトを利用する場合に指定します。
識別子(変数)に例外オブジェクトが格納されます。
この識別子(変数)はexcep節の最後にクリアされるで、他で使用することはできません。

else節

省略可能なオプションです。
例外(エラー)が発生しなかった場合のみ実行されます。
else節で起きた例外は、手前にあるexcept節では処理されません。

finally節

省略可能なオプションです。
後始末の処理です。
エラーの有無に関わらず実行されます。
finally節で起きた例外は、手前にあるexcept節では処理されません。

上記の説明文ではexcept節の使い方が分かりづらいと思います。
以下の使用例を通して、
例外ハンドラの指定やtry文のネストについての挙動を理解してください。


try文の使用例

先のスクリプトを例にtry文を順次組み込んでいきます。
def substr3(s):
    """文字列の3文字目を返す
    :param s: 入力文字列
    :return: sの3文字め
    """
    return s[2]
lang = ("Python","VBA","GAS","C","C##")
for s in lang:
    print(substr3(s))
上記のスクリプトを実行すると、
IndexError: string index out of range
このエラーになります。
try文を入れてスクリプトが停止しないようにします。

例外ハンドラを省略したexcept

forループ全体をtry文の中に入れてみます。
try:
    lang = ("Python","VBA","GAS","C","C##")
    for s in lang:
        print(substr3(s))
except:
    print("エラー発生")
例外ハンドラを省略しているので全てのエラーが捕捉できます。
上記を実行すると、

Python 例外処理 try except

エラーの捕捉はできていますが、そこでforループが終了してしまいます。
エラーになった場合でもforループを継続したい場合は、forの中にtry文を入れます。
lang = ("Python","VBA","GAS","C","C##")
for s in lang:
    try:
        print(substr3(s))
    except:
        print("エラー発生")
Python 例外処理 try except


例外ハンドラを指定したexcept

except節で具体的な例外ハンドラを指定します。
lang = ("Python","VBA","GAS","C","C##")
for s in lang:
    try:
        print(substr3(s))
    except IndexError as e:
        print(f"{s}:{e}")
Python 例外処理 try except

この場合はIndexError以外の例外には対応されません。
lang = ("Python","VBA",1234,"C","C##")
for s in lang:
    try:
        print(substr3(s))
    except IndexError as e:
        print(f"{s}:{e}")
Python 例外処理 try except
Python 例外処理 try except


複数の例外ハンドラの指定

except節に指定する例外ハンドラを複数指定します。
lang = ("Python","VBA",1234,"C","C##")
for s in lang:
    try:
        print(substr3(s))
    except IndexError as e:
        print(f"{s}:{e}")
    except TypeError as e:
        print(f"{s}:{e}")
Python 例外処理 try except

2つの例外に対応できていることが確認できます。
上記の2つのexcept節は中の処理が同じなので、1行にすることができます。
lang = ("Python","VBA",1234,"C","C##")
for s in lang:
    try:
        print(substr3(s))
    except (IndexError, TypeError) as e:
        print(f"{s}:{e}")

これでIndexErrorとTypeErrorの例外に対応できていますが、その他の例外が発生した場合はスクリプトが強制終了します。
想定外の例外でも終了しないようにするなら、以下のように例外ハンドラを指定しないexcept節を最後に付けておきます。
lang = ("Python","VBA",1234,"C","C##")
for s in lang:
    try:
        1/0
        print(substr3(s))
    except (IndexError, TypeError) as e:
        print(f"{s}:{e}")
    except:
        print("想定外のエラー")

try文のネスト

try文の中にtry文を入れて使います。
lang = ("Python","VBA","C",1234,"C##")
try:
    for s in lang:
        try:
            print(substr3(s))
        except IndexError as e:
            print(f"{s}:{e}")
except TypeError as e:
    print(f"{s}:{e}")
Python 例外処理 try except

for文の中のtryでは、IndexErrorのみに対処しています。
IndexError以外の例外が発生した場合は、for文の中のtryでは例外を補足できません。
この場合の例外発生時には、さらに上のレベル(外側)にtryがあるか探索されます。
tryがあり、合致するexcept節があればそこで補足されます。

上記スクリプトでは、IndexErrorはfor内のtryが捕捉し、TypeErrorは外側のtryが捕捉しています。


関数の中と呼び出し元の両方でtry文を使う

関数の中にtry文があり、その関数を呼び出しがtry文の中にある場合です。
def substr3(s):
    """文字列の3文字目を返す
    :param s: 入力文字列
    :return: sの3文字め
    """
    try:
        return s[2]
    except IndexError:
        return ""
lang = ("Python","VBA","C",1234,"C##")
for s in lang:
    try:
        print(substr3(s))
    except TypeError as e:
        print(f"{s}:{e}")
Python 例外処理 try except

関数の中のtryでは、IndexErrorのみに対処しています。
IndexError以外の例外が発生した場合は、関数の中のtryでは例外を補足できません。
この場合、例外発生時には、関数の呼び出し元にtryがあるか探索されます。
tryがあり、合致するexcept節があればそこで補足されます。

上記スクリプトでは、IndexErrorは関数内のtryが捕捉し、TypeErrorは呼び出し元のtryが捕捉しています。


else節とfinally節

else節とfinally節について、それぞれの挙動を理解しておきましょう。
def substr3(s):
    """文字列の3文字目を返す
    :param s: 入力文字列
    :return: sの3文字め
    """
    return s[2]
try:
    lang = ("Python","VBA","GAS","C","C##")
    for s in lang:
        print(substr3(s))
except:
    print("エラー発生")
else:
    print("全て正常")
finally:
    print("完了しました。")
Python 例外処理 try except

else節は例外が発生しなかった場合のみ処理されるので、上記では実行されていません。
入力するデータを以下に変更してみます。
lang = ("Python","VBA","GAS","PHP","C##")

Python 例外処理 try except

例外が発生しないのでelse節が処理されています。
そして、finally節は常に処理されていることが確認できます。


組み込み例外一覧

以下の一覧のリンクは、公式ドキュメントの当該の例外にリンクしています。

Base 全ての組み込み例外の基底クラスです。
ユーザ定義の例外に直接継承されることは意図されていません (継承にはExceptionを使ってください)。
exception システム終了以外の全ての組み込み例外はこのクラスから派生しています。
全てのユーザ定義例外もこのクラスから派生させるべきです。
ArithmeticError 算術上の様々なエラーに対して送出される組み込み例外
BufferError バッファに関連する操作が行えなかったときに送出されます。
LookupError マッピングまたはシーケンスで使われたキーやインデクスが無効な場合に送出される例外IndexErrorおよびKeyErrorの基底クラスです。

具象例外

AssertionError assert文が失敗した場合に送出されます。
AttributeError 属性参照 (属性参照を参照) や代入が失敗した場合に送出されます (オブジェクトが属性の参照や属性の代入をまったくサポートしていない場合にはTypeErrorが送出されます)。
EOFError input()が何もデータを読まずに end-of-file (EOF) に達した場合に送出されます。
FloatingPointError 現在は使われていません。
GeneratorExit ジェネレータやコルーチンが閉じられたときに送出されます。
この例外はエラーではなく技術的なものなので、ExceptionではなくBaseExceptionを直接継承しています。
ImportError import文でモジュールをロードしようとして問題が発生すると送出されます。
from...importの中の"from list" (訳注:...の部分)の名前が見つからないときにも送出されます。
ModuleNotFoundError ImportErrorのサブクラスで、import文でモジュールが見つからない場合に送出されます。
また、sys.modulesにNoneが含まれる場合にも送出されます。
IndexError シーケンスの添字が範囲外の場合に送出されます。
(スライスのインデクスはシーケンスの範囲に収まるように暗黙のうちに調整されます。
インデクスが整数でない場合、TypeErrorが送出されます。)
KeyError マッピング (辞書) のキーが、既存のキーの集合内に見つからなかった場合に送出されます。
KeyboardInterrupt ユーザが割り込みキー (通常はControl-CまたはDelete) を押した場合に送出されます。実行中、割り込みは定期的に監視されます。
Exceptionを捕捉するコードに誤って捕捉されてインタプリタの終了が阻害されないように、この例外はBaseExceptionを継承しています。
MemoryError ある操作中にメモリが不足したが、その状況は (オブジェクトをいくつか消去することで) まだ復旧可能かもしれない場合に送出されます。
NameError ローカルまたはグローバルの名前が見つからなかった場合に送出されます。
これは非修飾の (訳注:spam.eggではなく単にeggのような) 名前のみに適用されます。
関連値は見つからなかった名前を含むエラーメッセージです。
NotImplementedError この例外はRuntimeErrorから派生しています。
ユーザ定義の基底クラスにおいて、抽象メソッドが派生クラスでオーバライドされることを要求する場合にこの例外を送出しなくてはなりません。
またはクラスは実装中であり本来の実装を追加する必要があることを示します。
OSError([arg]) この例外はシステム関数がシステム関連のエラーを返した場合に送出されます。
OverflowError 算術演算の結果が表現できない大きな値になった場合に送出されます。
これは整数では起こりません (むしろMemoryErrorが送出されることになるでしょう)。
しかし、歴史的な理由のため、要求された範囲の外の整数に対して OverflowError が送出されることがあります。
C の浮動小数点演算の例外処理は標準化されていないので、ほとんどの浮動小数点演算もチェックされません。
RecursionError この例外はRuntimeErrorを継承しています。
インタープリタが最大再帰深度 (sys.getrecursionlimit()を参照) の超過を検出すると送出されます。
ReferenceError weakref.proxy()によって生成された弱参照 (weak reference) プロキシを使って、ガーベジコレクションによって回収された後の参照対象オブジェクトの属性にアクセスした場合に送出されます。
弱参照についてはweakrefモジュールを参照してください。
RuntimeError 他のカテゴリに分類できないエラーが検出された場合に送出されます。
関連値は、何が問題だったのかをより詳細に示す文字列です。
StopIteration 組込み関数next()とiteratorの__next__()メソッドによって、そのイテレータが生成するアイテムがこれ以上ないことを伝えるために送出されます。
StopAsyncIteration イテレーションを停止するために、asynchronous iteratorオブジェクトの__anext__()メソッドによって返される必要があります。
SyntaxError パーザが構文エラーに遭遇した場合に送出されます。
この例外はimport文、組み込み関数exec()やeval()、初期化スクリプトの読み込みや標準入力で (対話的な実行時にも) 起こる可能性があります。
IndentationError 正しくないインデントに関する構文エラーの基底クラスです。
これはSyntaxErrorのサブクラスです。
TabError タブとスペースを一貫しない方法でインデントに使っているときに送出されます。
これはIndentationErrorのサブクラスです。
SystemError インタプリタが内部エラーを発見したが、状況は全ての望みを棄てさせるほど深刻ではないと思われる場合に送出されます。
関連値は (下位層で) どの動作が失敗したかを示す文字列です。
SystemExit この例外はsys.exit()関数から送出されます。
Exceptionをキャッチするコードに誤ってキャッチされないように、ExceptionではなくBaseExceptionを継承しています。
これにより例外は上の階層に適切に伝わり、インタープリタを終了させます。
この例外が処理されなかった場合はスタックのトレースバックを表示せずに Python インタープリタは終了します。
TypeError 組み込み演算または関数が適切でない型のオブジェクトに対して適用された際に送出されます。
関連値は型の不整合に関して詳細を述べた文字列です。
UnboundLocalError 関数やメソッド内のローカルな変数に対して参照を行ったが、その変数には値が代入されていなかった場合に送出されます。
UnicodeError Unicode に関するエンコードまたはデコードのエラーが発生した際に送出されます。
UnicodeEncodeError Unicode 関連のエラーがエンコード中に発生した際に送出されます。
UnicodeDecodeError Unicode 関連のエラーがデコード中に発生した際に送出されます。
UnicodeTranslateError Unicode 関連のエラーが変換中に発生した際に送出されます。
ValueError 演算子や関数が、正しい型だが適切でない値を持つ引数を受け取ったときや、IndexErrorのようなより詳細な例外では記述できない状況で送出されます。
ZeroDivisionError 除算や剰余演算の第二引数が 0 であった場合に送出されます。
関連値は文字列で、その演算における被演算子と演算子の型を示します。

BlockingIOError ある操作が、ノンブロッキング操作に設定されたオブジェクト (例えばソケット) をブロックしそうになった場合に送出されます。
ChildProcessError 子プロセスの操作が失敗した場合に送出されます。
ConnectionError コネクション関係の問題の基底クラス。
BrokenPipeError ConnectionErrorのサブクラスで、もう一方の端が閉じられたパイプに書き込こもうとするか、書き込みのためにシャットダウンされたソケットに書き込こもうとした場合に発生します。
ConnectionAbortedError ConnectionErrorのサブクラスで、接続の試行が通信相手によって中断された場合に発生します。
ConnectionRefusedError ConnectionErrorのサブクラスで、接続の試行が通信相手によって拒否された場合に発生します。
ConnectionResetError ConnectionErrorのサブクラスで、接続が通信相手によってリセットされた場合に発生します。
FileExistsError すでに存在するファイルやディレクトリを作成しようとした場合に送出されます。
FileNotFoundError 要求されたファイルやディレクトリが存在しない場合に送出されます。
InterruptedError システムコールが入力信号によって中断された場合に送出されます。
IsADirectoryError ディレクトリに (os.remove()などの) ファイル操作が要求された場合に送出されます。
NotADirectoryError ディレクトリ以外のものに (os.listdir()などの) ディレクトリ操作が要求された場合に送出されます。
PermissionError 十分なアクセス権、例えばファイルシステム権限のない操作が試みられた場合に送出されます。
ProcessLookupError 与えられたプロセスが存在しない場合に送出されます。
TimeoutError システム関数がシステムレベルでタイムアウトした場合に送出されます。




同じテーマ「Python入門」の記事

第15回.lambda(ラムダ式、無名関数)と三項演算子
第16回.Pythonの引数は参照渡しだが・・・
第17回.リスト内包表記
第18回.例外処理(try文)とexception一覧
第19回.import文(パッケージ・モジュールのインポート)
第20回.フォルダとファイルの一覧を取得(os,glob,pathlib)
第21回.CSV読み込みとopen()関数とwith文
第22回.CSV読み書き(csvモジュール)
第23回.pipコマンド(外部ライブラリのインストール)
第24回.エクセルを操作する(openpyxl)
第25回.エクセルを操作する(pywin32:win32com)


新着記事NEW ・・・新着記事一覧を見る

WEBスクレイピング(selenium)|Python入門(10月11日)
エクセルを操作する(pywin32:win32com)|Python入門(10月5日)
エクセルを操作する(openpyxl)|Python入門(10月3日)
pipコマンド(外部ライブラリのインストール)|Python入門(10月1日)
CSV読み書き(csvモジュール)|Python入門(9月29日)
「Excel 4.0 マクロ」の使い方|VBA技術解説(9月28日)
CSV読み込みとopen()関数とwith文|Python入門(9月28日)
フォルダとファイルの一覧を取得(os,glob,pathlib)|Python入門(9月26日)
import文(パッケージ・モジュールのインポート)|Python入門(9月24日)
例外処理(try文)とexception一覧|Python入門(9月23日)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.変数宣言のDimとデータ型|VBA入門
4.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
5.マクロって何?VBAって何?|VBA入門
6.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
7.繰り返し処理(For Next)|VBA入門
8.セルに文字を入れるとは(Range,Value)|VBA入門
9.とにかく書いてみよう(Sub,End Sub)|VBA入門
10.マクロはどこに書くの(VBEの起動)|VBA入門




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。



このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ