Pythonの例外をサクサク理解しよう特集:Visual Studioで始めるPythonプログラミング(4/4 ページ)

» 2017年01月13日 05時00分 公開
[かわさきしんじInsider.NET編集部]
前のページへ 1|2|3|4       

例外の送出

 ここまでプログラム実行時に発生した例外の処理を見てきたが、raise文を使用することで、任意の例外を任意の時点で送出できる。

 最も分かりやすい例を以下に示す(これまでと同様、[Interactive]ウィンドウでの実行結果)。

>>> raise RuntimeError
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError


RuntimeError例外の送出

 このとき、コンストラクタにエラーメッセージを引き渡すこともできる(強調書体部分に注目)。

>>> raise RuntimeError('hello from runtime error')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: hello from runtime error


エラーメッセージの指定

 例外処理時に、その例外を適切に処理できなかったときには単に「raise」とするだけで、例外が再送出される。以下に例を示す。ここでは関数funcが例外を処理せずに、再送出するようにしている。また、関数callerから関数funcを呼び出すことを想定している。関数callerでは例外処理をしていないことに注意。

def func(exp):
  try:
    return eval(exp)
  except ZeroDivisionError:
    print('division by zero')
    raise
  except NameError as e:
    print('undefined name')
    raise
  except Exception as e:
    print('some exception!', e)
    raise RuntimeError(e.args) from e

def caller():
  x = input('input expression:')
  print(func(x))


修正した関数funcとそれを呼び出す関数caller

 最後の「except Exception from e」行では、発生した例外からさらに例外を発生させている(例外の連鎖)。このときには、新たに発生した例外の原因を「from」に続けて記述する。

 実行例を以下に示す。なお、ここでは上のコードをexceptionsample.pyファイルに保存し、これを[Interactive]ウィンドウでインポートしている([Interactive]ウィンドウでうまく動かないときにはVisual Studioを再起動するか、コマンドラインのpythonコマンドで対話環境を起動するなどしてみてほしい)。

>>> from exceptionsample import func, caller
>>> caller()  # 例外の再送出
input expression:
1/0

division by zero
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File ".\exceptionsample.py", line 16, in caller
    print(func(x))
  File ".\exceptionsample.py", line 3, in func
    return eval(exp)
  File "<string>", line 1, in <module>
ZeroDivisionError: division by zero
>>> caller()  # 例外の連鎖
input expression:
1 + str(100)

some exception! unsupported operand type(s) for +: 'int' and 'str'
Traceback (most recent call last):
  File ".\exceptionsample.py", line 3, in func
    return eval(exp)
  File "<string>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File ".\exceptionsample.py", line 16, in caller
    print(func(x))
  File ".\exceptionsample.py", line 12, in func
    raise RuntimeError(e.args) from e
RuntimeError: ("unsupported operand type(s) for +: 'int' and 'str'",)


実行例

 最初の例(「1/0」)では、exceptionsample.pyファイルの3行目(「eval(exp)」行)で発生した例外がそのまま再送出されている。一方、2つ目の例では、同様に3行目で発生したTypeError例外を直接の原因としてRuntimeError例外が送出されたことが分かる(スタックトレースが2つあり、その後者の「raise RuntimeError(e.args) from e」でRuntimeError例外が送出されたことが分かる)。関数caller側では元の関数funcと同様にして再送出された例外を処理できる(コードは割愛)。

 独自の例外クラスも作成できる。以下に簡単な例を示す。

class MyException(Exception):
  def __init__(self, message):
    self.message = message

try:
  raise MyException('hello')
except MyException as e:
  print(e)


独自の例外クラスの作成

 ポイントはExceptionクラスまたはその派生クラスを、独自クラスの基底クラスとすることだ。Pythonではユーザー定義の例外クラスはExceptionクラスの派生クラスであることが必要となっているので注意しよう(実行結果は割愛)。


 本稿では、Pythonの例外の基礎について見てきた。Pythonでは例外がtry〜except〜else〜finally文で取り扱う。exceptではキャッチする例外を指定したり、例外オブジェクトを取得したりできる。else節はtry節で例外が発生されなかったときに実行され、finally節はtry節での例外の有無に関係なく実行される。各節がどのような順序で実行されるかは(本稿では触れなかったが、例外の再送出が絡んだ場合にはより一層の)注意が必要だ。次回は、落ち穂拾い的にさまざまな要素を取り上げていくことにしよう。

「特集:Visual Studioで始めるPythonプログラミング」のインデックス

特集:Visual Studioで始めるPythonプログラミング

前のページへ 1|2|3|4       

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。