『Python基礎教程』第8章異常

5952 ワード

この章では、カスタム例外の作成と開始、および例外の処理方法について説明します.
8.1異常とは
プログラムの実行中のエラーや望ましくないことが異常です.このようなイベントを防ぐために多くの条件文を使用することができますが、コストが非常に高く、効率的ではありません.
Pythonでは、異常オブジェクト(exception object)で異常を表します.異常オブジェクトが処理またはスナップされていない場合、プログラムは遡及を使用します.(Traceback、エラーメッセージ)プログラムを終了します.実際には、各例外はいくつかの例外クラスのインスタンスであり、例外クラスのインスタンスは異なる状況で開始され、プログラムの実行に失敗することなくキャプチャされた後にエラー処理を行うことができます.
8.2自分のやり方で間違いを犯す
8.2.1 raise文
組み込まれた例外クラスが多く、Pythonのドキュメント「Built-in Exception」の関連部分を詳しく説明しています.
dirを使用してexceptionsモジュールの内容をリストできます.
>>> import exceptions
>>> dir(exceptions)
['ArithmeticError', 'AssertionError', ...]

次に、組み込み例外クラスを使用する簡単な例を示します.
>>> raise Exception
Traceback (most recent call last):
  File "", line 1, in 
Exception
>>> raise Exception('hyperdriver overload')
Traceback (most recent call last):
  File "", line 1, in 
Exception: hyperdriver overload

8.2.2カスタム例外クラス
組み込み例外クラスがプログラムの要件を満たすことができない場合は、例外クラスをカスタマイズできます.カスタム例外クラスが直接または間接的にExceptionクラスから継承されることを保証するだけです.
class SomeCustomException(Expception): pass

8.3捕捉異常
ユーザーに2つの数を入力して削除するプログラムがある場合は、次のようにします.
n = input('Enter your first number:')
m = input('Enter your second number:')
print n / m


$ python class.py
Enter your first number:10
Enter your second number:0
Traceback (most recent call last):
  File "class.py", line 3, in 
    print n / m
ZeroDivisionError: integer division or modulo by zero


例外をキャプチャして処理できます.
try:
    n = input('Enter your first number:')
    m = input('Enter your second number:')
    print n / m
except ZeroDivisionError:
    print 'The second number can not be zero!'

$ python class.py
Enter your first number:10
Enter your second number:0
The second number can not be zero!

異常をキャプチャして情報を印刷したが,実際には処理せずに伝達を続けることができる.
以下に、「マスク」ZeroDivisionErrorエラーのコード例を示します.muffled=Fasleの場合、エラーメッセージが直接印刷されます.そうでない場合、例外は上位呼び出し者に渡されます.

class MuffledCalculator:
    muffled = False
    def calc(self, expr):
        try:
            return eval(expr)
        except ZeroDivisionError:
            if self.muffled:
                print 'Division by zero is illegal.'
            else:
                raise
>>> c = MuffledCalculator()
>>> c.calc("12/0")

Traceback (most recent call last):
  File "class.py", line 12, in 
    c.calc("12/0")
  File "class.py", line 5, in calc
    return eval(expr)
  File "", line 1, in 
>>> c.muffled = true
>>> c.calc("12/0")
ZeroDivisionError: integer division or modulo by zero


8.4複数のexcept句
前の例では、ユーザーが入力した文字列であれば、直接除算演算を行うとTypeErrorの異常を引き起こす可能性があります.この場合、複数のexcept句を使用できます.
try:
    n = input('Enter your first number:')
    m = input('Enter your second number:')
    print n / m
except ZeroDivisionError:
    print 'The second number can not be zero!'
except TypeError:
    print 'That was not number, is it?'

8.5一つのブロックで二つの異常を捕捉する
前節の複数の異常は、単独で処理する必要がなければ、より簡潔にメタグループで表すことができる.
try:
    n = input('Enter your first number:')
    m = input('Enter your second number:')
    print n / m
except (ZeroDivisionError, TypeError, NameError):
    print 'Your number was bongus!'

もちろん、エラー情報を印刷するだけでは意味がありません.もう一つの方法は、演算ビットが可能になるまで合理的な数字を入力することです.
8.6オブジェクトのスナップ
プログラムの実行を終了したくない場合、except句でエラー情報を取得したい場合は、例外オブジェクトに直接アクセスできます.
try:
    n = input('Enter your first number:')
    m = input('Enter your second number:')
    print n / m
except (ZeroDivisionError, TypeError, NameError), e:
    print e

$ python class.py
Enter your first number:10
Enter your second number:0
integer division or modulo by zero

8.7本格的なフルスナップ
上記の例では、ユーザーが何も入力せずに直接車に戻るなど、try/exceptのチェックを避けるユーザー操作があります.
$ python class.py
Enter your first number:
Traceback (most recent call last):
  File "class.py", line 2, in 
    n = input('Enter your first number:')
  File "", line 0
    
    ^
SyntaxError: unexpected EOF while parsing

Pythonがすべての異常をすべてキャプチャするには、exceptの句に異常クラスを書かないでください.
try:
    n = input('Enter your first number:')
    m = input('Enter your second number:')
    print n / m
except:
    print 'Something wrong happen...'

8.8万事順調
try/except句では、exceptionが発生するとexceptブランチが実行され、exceptionが発生しない場合はelseブランチが追加されます.次の例を示します.
try:
    print 'A Simple Task'
except:
    print 'What? Something went wrong!'
else:
    print 'Ah... I went as planed'

$ python class.py
A Simple Task
Ah... I went as planed

8.9最後
else句に加えて、finally句はクリーンアップ作業に使用できます(finally句は異常が発生しているかどうかにかかわらず実行されます):
try:
    1/o
except NameError:
    print 'Unknown variable!'
else:
    print 'That wents well'
finally:
    print 'Clean up'
$ python class.py
Unknown variable!
Clean up

8.10異常と関数
異常が関数で処理されていない場合、処理されるまで関数呼び出しの場所に伝播されます.
8.11異常の禅
try/exceptとif/else句は、場合によっては同様の機能を実現することができるが、if/elseは自然性と可読性が劣り、できるだけtry/exceptを多く使用する習慣を身につけなければならない.
「一つのことをする過程で、このことをする前に大量の検査をするのではなく、発生する可能性のある間違いを処理します」.
8.12まとめ
  • 異常対象
  • 警告[注:この章はもともと警告に言及していません]
  • 異常発生
  • カスタム例外クラス
  • 捕捉異常
  • else句
  • 異常と関数
  • 8.12.1この章の新しい関数

    8.12.2次に何を勉強しますか.