exceptions – ビルトインエラークラス

目的:例外モジュールはインタープリタや標準ライブラリで使用されるビルトインエラーを定義する
利用できるバージョン:1.5 以上

説明

これまでに Python はクラス同様に例外として単純な文字列のメッセージに対応していました。Python 1.5 以降、全ての標準ライブラリモジュールはクラス例外を使用します。Python 2.5 を使用すると文字列例外は DeprecationWarning を発生させます。そして、文字列例外のサポートは今後廃止される予定です。

ベースクラス

例外クラスは階層構造で定義されていて、標準ライブラリドキュメントに説明があります。明らかな階層化の利点に加えて、継承された例外のベースクラスを捕捉することで関連する例外をまとめて捕捉できるので例外の継承は役に立ちます。大半のケースでは、ベースクラスは直接発生させることを目的としていません。

BaseException

全ての例外のベースクラスです。そのコンストラクタへ渡される引数から str() を使用してその例外の説明メッセージを作成するロジックを実装してください。

Exception

実行中のアプリケーションを終了させない例外のためのベースクラスです。全てのユーザ定義の例外はベースクラスとして Exception を使用すべきです。

StandardError

ビルトイン例外のベースクラスは標準ライブラリで使用されます。

ArithmeticError

数値関連のエラーのためのベースクラスです。

LookupError

何かを発見したときに発生させるエラーのベースクラスです。

EnvironmentError

Python の外部(オペレーティングシステム、ファイルシステム等)から発生するエラーのためのベースクラスです。

例外を発生させる

AssertionError

assert 文が失敗したときに AssertionError が発生します。

assert False, 'The assertion failed'
$ python exceptions_AssertionError_assert.py
Traceback (most recent call last):
  File "exceptions_AssertionError_assert.py", line 12, in <module>
    assert False, 'The assertion failed'
AssertionError: The assertion failed

failIf() のようなメソッドで unittest モジュールでも使用されます。

import unittest

class AssertionExample(unittest.TestCase):
    
    def test(self):
        self.failUnless(False)

unittest.main()
$ python exceptions_AssertionError_unittest.py
F
======================================================================
FAIL: test (__main__.AssertionExample)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "exceptions_AssertionError_unittest.py", line 17, in test
    self.failUnless(False)
AssertionError: False is not true

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (failures=1)

AttributeError

属性の参照か割り当てが失敗したときに AttributeError が発生します。例えば、存在しない属性を参照しようとしたときに発生します。

class NoAttributes(object):
    pass

o = NoAttributes()
print o.attribute
$ python exceptions_AttributeError.py
Traceback (most recent call last):
  File "exceptions_AttributeError.py", line 16, in <module>
    print o.attribute
AttributeError: 'NoAttributes' object has no attribute 'attribute'

又は読み込み専用属性を変更しようとしたときに発生します。

class MyClass(object):
    
    @property
    def attribute(self):
        return 'This is the attribute value'

o = MyClass()
print o.attribute
o.attribute = 'New value'
$ python exceptions_AttributeError_assignment.py
This is the attribute value
Traceback (most recent call last):
  File "exceptions_AttributeError_assignment.py", line 20, in <module>
    o.attribute = 'New value'
AttributeError: can't set attribute

EOFError

input() 又は raw_input() のようなビルトイン関数が入力ストリームの最後に遭遇する前にデータを読み込めないときに EOFError が発生します。 read() のような file メソッドはファイルの最後で空文字列を返します。

while True:
    data = raw_input('prompt:')
    print 'READ:', data
$ echo hello | python PyMOTW/exceptions/exceptions_EOFError.py
prompt:READ: hello
prompt:Traceback (most recent call last):
  File "PyMOTW/exceptions/exceptions_EOFError.py", line 13, in <module>
    data = raw_input('prompt:')
EOFError: EOF when reading a line

FloatingPointError

浮動小数点例外制御(fpectl)がオンのとき、最終的にエラーを引き起こす浮動小数点の操作で発生します。 fpectl を有効にするには --with-fpectl フラグをセットしてコンパイルされたインタープリタが必要です。 fpectl を使用することは 標準ライブラリドキュメントでは推奨されていません

import math
import fpectl

print 'Control off:', math.exp(1000)
fpectl.turnon_sigfpe()
print 'Control on:', math.exp(1000)

GeneratorExit

ジェネレータの close() メソッドが呼ばれるときにジェネレータ内部で発生します。

def my_generator():
    try:
        for i in range(5):
            print 'Yielding', i
            yield i
    except GeneratorExit:
        print 'Exiting early'

g = my_generator()
print g.next()
g.close()
$ python exceptions_GeneratorExit.py
Yielding 0
0
Exiting early

IOError

入力や出力が失敗するときに発生します。例えば、ディスクがいっぱいだったり、入力ファイルが存在しないときに発生します。

f = open('/does/not/exist', 'r')
$ python exceptions_IOError.py
Traceback (most recent call last):
  File "exceptions_IOError.py", line 12, in <module>
    f = open('/does/not/exist', 'r')
IOError: [Errno 2] No such file or directory: '/does/not/exist'

ImportError

あるモジュール、又はモジュールのメンバがインポートできないときに発生します。ImportError が発生する個所には複数の条件があります。

  1. モジュールが存在しない場合
import module_does_not_exist
$ python exceptions_ImportError_nomodule.py
Traceback (most recent call last):
  File "exceptions_ImportError_nomodule.py", line 12, in <module>
    import module_does_not_exist
ImportError: No module named module_does_not_exist
  1. from X import Y が使用されてモジュール X の内部で Y が見つからなかった場合
from exceptions import MadeUpName
$ python exceptions_ImportError_missingname.py
Traceback (most recent call last):
  File "exceptions_ImportError_missingname.py", line 12, in <module>
    from exceptions import MadeUpName
ImportError: cannot import name MadeUpName

IndexError

IndexError はシーケンスの範囲外を参照したときに発生します。

my_seq = [ 0, 1, 2 ]
print my_seq[3]
$ python exceptions_IndexError.py
Traceback (most recent call last):
  File "exceptions_IndexError.py", line 13, in <module>
    print my_seq[3]
IndexError: list index out of range

KeyError

同様に KeyError は辞書のキーが見つからなかったときに発生します。

d = { 'a':1, 'b':2 }
print d['c']
$ python exceptions_KeyError.py
Traceback (most recent call last):
  File "exceptions_KeyError.py", line 13, in <module>
    print d['c']
KeyError: 'c'

KeyboardInterrupt

ユーザが実行中のプログラムを停止するために Ctrl-C (又は Delete) を押下すると KeyboardInterrupt が発生します。その他のほとんどの例外と違い、Exception を捕捉するグローバルな例外ハンドラによって捕捉されないように KeyboardInterrupt は BaseException から直接継承します。

try:
    print 'Press Return or Ctrl-C:',
    ignored = raw_input()
except Exception, err:
    print 'Caught exception:', err
except KeyboardInterrupt, err:
    print 'Caught KeyboardInterrupt'
else:
    print 'No exception'

プロンプトで Ctrl-C を押下すると KeyboardInterrupt 例外を引き起こします。

$ python exceptions_KeyboardInterrupt.py
Press Return or Ctrl-C: ^CCaught KeyboardInterrupt

MemoryError

実行中のプログラムがメモリ不足になったら、MemoryError を発生させてリカバリ(例えば、オブジェクトを削除する)することができます。

import itertools

# 大量のメモリを割り当てることで MemoryError の発生を試みる
l = []
for i in range(3):
    try:
        for j in itertools.count(1):
            print i, j
            l.append('*' * (2**30))
    except MemoryError:
        print '(error, discarding existing list)'
        l = []
$ python exceptions_MemoryError.py
python(49670) malloc: *** mmap(size=1073745920) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
python(49670) malloc: *** mmap(size=1073745920) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
python(49670) malloc: *** mmap(size=1073745920) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
0 1
0 2
0 3
(error, discarding existing list)
1 1
1 2
1 3
(error, discarding existing list)
2 1
2 2
2 3
(error, discarding existing list)

NameError

カレントスコープに存在しない名前を参照するときに NameErrors が発生します。例えば、資格のない変数名です。

def func():
    print unknown_name

func()
$ python exceptions_NameError.py
Traceback (most recent call last):
  File "exceptions_NameError.py", line 15, in <module>
    func()
  File "exceptions_NameError.py", line 13, in func
    print unknown_name
NameError: global name 'unknown_name' is not defined

NotImplementedError

サブクラスで定義する必要のあるメソッド又は振る舞いを表すために、 インタフェース を模倣してユーザ定義のベースクラスは NotImplementedError を発生させます。

class BaseClass(object):
    """Defines the interface"""
    def __init__(self):
        super(BaseClass, self).__init__()
    def do_something(self):
        """The interface, not implemented"""
        raise NotImplementedError(self.__class__.__name__ + '.do_something')

class SubClass(BaseClass):
    """Implementes the interface"""
    def do_something(self):
        """really does something"""
        print self.__class__.__name__ + ' doing something!'

SubClass().do_something()
BaseClass().do_something()
$ python exceptions_NotImplementedError.py
SubClass doing something!
Traceback (most recent call last):
  File "exceptions_NotImplementedError.py", line 27, in <module>
    BaseClass().do_something()
  File "exceptions_NotImplementedError.py", line 18, in do_something
    raise NotImplementedError(self.__class__.__name__ + '.do_something')
NotImplementedError: BaseClass.do_something

See also

abc - 抽象基底クラス

OSError

OSError は os モジュールのエラークラスとして OS に特化した機能からエラーが返されるときに発生します。

import os

for i in range(10):
    print i, os.ttyname(i)
$ python exceptions_OSError.py
0 /dev/ttys049
1
Traceback (most recent call last):
  File "exceptions_OSError.py", line 15, in <module>
    print i, os.ttyname(i)
OSError: [Errno 25] Inappropriate ioctl for device

OverflowError

数値の操作が変数のデータ型の最大値を超えるときに OverflowError が発生します。long int は巨大な値のためにより多くの領域を割り当てます。そのため、最終的には MemoryError が発生します。浮動小数点の例外は標準化されていないので浮動小数はチェックされません。必要に応じて普通の int 型から long 型へ変換されます。

import sys

print 'Regular integer: (maxint=%s)' % sys.maxint
try:
    i = sys.maxint * 3
    print 'No overflow for ', type(i), 'i =', i
except OverflowError, err:
    print 'Overflowed at ', i, err

print
print 'Long integer:'
for i in range(0, 100, 10):
    print '%2d' % i, 2L ** i

print
print 'Floating point values:'
try:
    f = 2.0**i
    for i in range(100):
        print i, f
        f = f ** 2
except OverflowError, err:
    print 'Overflowed after ', f, err
$ python exceptions_OverflowError.py
Regular integer: (maxint=9223372036854775807)
No overflow for  <type 'long'> i = 27670116110564327421

Long integer:
 0 1
10 1024
20 1048576
30 1073741824
40 1099511627776
50 1125899906842624
60 1152921504606846976
70 1180591620717411303424
80 1208925819614629174706176
90 1237940039285380274899124224

Floating point values:
0 1.23794003929e+27
1 1.53249554087e+54
2 2.34854258277e+108
3 5.5156522631e+216
Overflowed after  5.5156522631e+216 (34, 'Result too large')

ReferenceError

ガベージコレクトされたオブジェクトへ weakref プロキシを使用してアクセスするときに ReferenceError が発生します。

import gc
import weakref

class ExpensiveObject(object):
    def __init__(self, name):
        self.name = name
    def __del__(self):
        print '(Deleting %s)' % self

obj = ExpensiveObject('obj')
p = weakref.proxy(obj)

print 'BEFORE:', p.name
obj = None
print 'AFTER:', p.name
$ python exceptions_ReferenceError.py
BEFORE: obj
(Deleting <__main__.ExpensiveObject object at 0x1004704d0>)
AFTER:
Traceback (most recent call last):
  File "exceptions_ReferenceError.py", line 26, in <module>
    print 'AFTER:', p.name
ReferenceError: weakly-referenced object no longer exists

RuntimeError

他に適切な例外がないときに RuntimeError 例外が使用されます。インタープリタはこの例外を滅多に発生させませんが、ユーザコードによっては RuntimeError を発生させます。

StopIteration

イテレータが終了したときに、そのイテレータの next() メソッドは StopIteration を発生させます。この例外はエラーと見なされません。

l=[0,1,2]
i=iter(l)

print i
print i.next()
print i.next()
print i.next()
print i.next()
$ python exceptions_StopIteration.py
<listiterator object at 0x100460650>
0
1
2
Traceback (most recent call last):
  File "exceptions_StopIteration.py", line 19, in <module>
    print i.next()
StopIteration

SyntaxError

パーサが解析できないソースコードを見つけたときに SyntaxError が発生します。この例外はモジュールのインポート、 exec を実行したり、 eval() を呼び出したりするときに発生する可能性があります。例外の属性はこの例外を引き起こしたのがソースコードのどのテキストなのかを厳密に見つけるために使用されます。

try:
    print eval('five times three')
except SyntaxError, err:
    print 'Syntax error %s (%s-%s): %s' % \
        (err.filename, err.lineno, err.offset, err.text)
    print err
$ python exceptions_SyntaxError.py
Syntax error <string> (1-10): five times three
invalid syntax (<string>, line 1)

SystemError

インタープリタそのものでエラーが発生しても正常に実行を継続する可能性があるときに SystemError が発生します。SystemErrors は、おそらくはインタープリタのバグを表し、メンテナへ報告すべきです。

SystemExit

sys.exit() が呼び出されるとき、即時終了する代わりに SystemExit が発生します。これは try:finally ブロックのクリーンアップコードの実行、例外を捕捉するための(デバッガやテストフレームワークのような)特別な環境や処理を終了させないようにします。

TypeError

誤ったオブジェクトのデータ型を結合する、又は誤ったオブジェクトのデータ型で関数を呼び出すことで TypeErrors が発生します。

result = ('tuple',) + 'string'
$ python exceptions_TypeError.py
Traceback (most recent call last):
  File "exceptions_TypeError.py", line 12, in <module>
    result = ('tuple',) + 'string'
TypeError: can only concatenate tuple (not "str") to tuple

UnboundLocalError

UnboundLocalError はローカル変数の名前に特化した NameError の一種です。

def throws_global_name_error():
    print unknown_global_name

def throws_unbound_local():
    local_val = local_val + 1
    print local_val

try:
    throws_global_name_error()
except NameError, err:
    print 'Global name error:', err

try:
    throws_unbound_local()
except UnboundLocalError, err:
    print 'Local name error:', err

グローバルな NameError と UnboundLocal の違いはその名前の使用方法です。”local_val” という名前が式の左側に現れるのでローカル変数の名前として解釈されます。

$ python exceptions_UnboundLocalError.py
Global name error: global name 'unknown_global_name' is not defined
Local name error: local variable 'local_val' referenced before assignment

UnicodeError

UnicodeErrorValueError のサブクラスでユニコードに関する問題で発生します。さらに UnicodeEncodeError, UnicodeDecodeErrorUnicodeTranslateError といったサブクラスに分割されます。

ValueError

ある関数の受け取る値が正しい型で不正な値を持つときに ValueError が発生します。

print chr(1024)
$ python exceptions_ValueError.py
Traceback (most recent call last):
  File "exceptions_ValueError.py", line 12, in <module>
    print chr(1024)
ValueError: chr() arg not in range(256)

ZeroDivisionError

除算の分母がゼロのとき ZeroDivisionError が発生します。

print 1/0
$ python exceptions_ZeroDivisionError.py
Traceback (most recent call last):
  File "exceptions_ZeroDivisionError.py", line 12, in <module>
    print 1/0
ZeroDivisionError: integer division or modulo by zero

警告のカテゴリ

warnings モジュールと一緒に使用する複数の例外もあります。

Warning
全ての warnings のベースクラス
UserWarning
ユーザコードから返される warnings のベースクラス
DeprecationWarning
今後はメンテナンスされない機能に使用される
PendingDeprecationWarning
すぐに廃止予定の機能に使用される
SyntaxWarning
怪しい構文に使用される
RuntimeWarning
実行時に問題を引き起こすかもしれないイベントに使用される
FutureWarning
言語又はライブラリがその後に変更されることに関して警告する
ImportWarning
モジュールインポートの問題に関して警告する
UnicodeWarning
ユニコードテキストの問題に関して警告する

See also

exceptions
本モジュールの標準ライブラリドキュメント
warnings
エラーではない警告メッセージ
Bookmark and Share