Python Language
例外
サーチ…
前書き
実行中に検出されたエラーは例外と呼ばれ、無条件に致命的ではありません。ほとんどの例外はプログラムによって処理されません。選択した例外を処理するプログラムを記述することができます。 Pythonには、例外や例外ロジックを扱う特定の機能があります。さらに、例外には豊富な型階層があり、すべてBaseException
型を継承しています。
構文
- 例外を提起する
- raise#すでに発生している例外を再発生させる
- 原因を#Pythonから引き上げる3 - 例外の原因を設定する
- 例外をNoneから出す#Python 3 - すべての例外コンテキストを抑止する
- 試してください:
- [ 識別子として] [例外タイプ]を除きます。
- else:
- 最後に:
例外の発生
コードが条件に遭遇した場合、不適切なパラメータなどの処理方法がわからない場合は、適切な例外が発生するはずです。
def even_the_odds(odds):
if odds % 2 != 1:
raise ValueError("Did not get an odd number")
return odds + 1
例外のキャッチ
例外をキャッチするには、 try...except:
を使用します。次のように、正確な例外を指定する必要があります。
try:
x = 5 / 0
except ZeroDivisionError as e:
# `e` is the exception object
print("Got a divide by zero! The exception was:", e)
# handle exceptional case
x = 0
finally:
print "The END"
# it runs no matter what execute.
指定された例外クラス(この場合はZeroDivisionError
は、そのクラスまたはその例外のサブクラスであるすべての例外をキャッチします。
たとえば、 ZeroDivisionError
はArithmeticError
サブクラスです。
>>> ZeroDivisionError.__bases__
(<class 'ArithmeticError'>,)
したがって、次のZeroDivisionError
ます:
try:
5 / 0
except ArithmeticError:
print("Got arithmetic error")
最終的にクリーンアップコードを実行する
場合によっては、何らかのリソースがクリーンアップされなければならないなど、例外が発生した場合でも、発生するものが必要な場合があります。
try
節のfinally
ブロックは、例外が発生したかどうかにかかわらず発生します。
resource = allocate_some_expensive_resource()
try:
do_stuff(resource)
except SomeException as e:
log_error(e)
raise # re-raise the error
finally:
free_expensive_resource(resource)
このパターンは、( with
ステートメントを使用しwith
)コンテキストマネージャーでよく扱われることがよくあります。
例外の再発生
場合によっては、例えばログを採取するために、検査するために例外をキャッチすることがあります。検査の後、前と同じように例外が伝搬し続けるようにします。
この場合、引数なしでraise
文を使用するだけです。
try:
5 / 0
except ZeroDivisionError:
print("Got an error")
raise
ただし、呼び出し元スタックの上位のユーザーが例外をキャッチして何とか処理できることに注意してください。完成した出力は、いずれの場合にも発生するため、この場合は迷惑になる可能性があります(キャッチまたはキャッチされません)。だから、元の例外と同様に状況についてのあなたのコメントを含む別の例外を発生させる方が良いかもしれません:
try:
5 / 0
except ZeroDivisionError as e:
raise ZeroDivisionError("Got an error", e)
しかしこれには、例外トレースを正確にこのraise
に減らすという欠点があり、引数なしのraise
は元の例外トレースを保持します。
Python 3では、 raise
- from
構文を使って元のスタックを保持することができます:
raise ZeroDivisionError("Got an error") from e
発生元のチェーン例外
例外を処理するプロセスでは、別の例外を発生させることができます。たとえば、ファイルから読み込み中にIOError
が発生した場合、アプリケーション固有のエラーを発生させて、ライブラリのユーザーに提示することができます。
例外処理をどのように処理したかを示すために、例外を連結することができます。
>>> try:
5 / 0
except ZeroDivisionError as e:
raise ValueError("Division failed") from e
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ZeroDivisionError: division by zero
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
ValueError: Division failed
例外階層
例外処理は、例外クラスの継承構造によって決定される例外階層に基づいて行われます。
たとえば、 IOError
とOSError
は両方ともEnvironmentError
サブクラスです。 IOError
を捕捉するOSError
はOSError
捕捉しません。ただし、 EnvironmentError
を捕捉するコードは、 IOError
とOSError
の両方を捕捉しIOError
。
組み込み例外の階層:
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StandardError
| +-- BufferError
| +-- ArithmeticError
| | +-- FloatingPointError
| | +-- OverflowError
| | +-- ZeroDivisionError
| +-- AssertionError
| +-- AttributeError
| +-- EnvironmentError
| | +-- IOError
| | +-- OSError
| | +-- WindowsError (Windows)
| | +-- VMSError (VMS)
| +-- EOFError
| +-- ImportError
| +-- LookupError
| | +-- IndexError
| | +-- KeyError
| +-- MemoryError
| +-- NameError
| | +-- UnboundLocalError
| +-- ReferenceError
| +-- RuntimeError
| | +-- NotImplementedError
| +-- SyntaxError
| | +-- IndentationError
| | +-- TabError
| +-- SystemError
| +-- TypeError
| +-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StopAsyncIteration
+-- ArithmeticError
| +-- FloatingPointError
| +-- OverflowError
| +-- ZeroDivisionError
+-- AssertionError
+-- AttributeError
+-- BufferError
+-- EOFError
+-- ImportError
+-- LookupError
| +-- IndexError
| +-- KeyError
+-- MemoryError
+-- NameError
| +-- UnboundLocalError
+-- OSError
| +-- BlockingIOError
| +-- ChildProcessError
| +-- ConnectionError
| | +-- BrokenPipeError
| | +-- ConnectionAbortedError
| | +-- ConnectionRefusedError
| | +-- ConnectionResetError
| +-- FileExistsError
| +-- FileNotFoundError
| +-- InterruptedError
| +-- IsADirectoryError
| +-- NotADirectoryError
| +-- PermissionError
| +-- ProcessLookupError
| +-- TimeoutError
+-- ReferenceError
+-- RuntimeError
| +-- NotImplementedError
| +-- RecursionError
+-- SyntaxError
| +-- IndentationError
| +-- TabError
+-- SystemError
+-- TypeError
+-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
+-- ResourceWarning
例外もオブジェクトです
例外は、組み込みのBaseException
を継承する単なる通常のPythonオブジェクトです。 Pythonスクリプトはraise
文を使用して実行を中断することができ、Pythonはその時点で呼び出しスタックのスタックトレースと例外インスタンスの表現を出力します。例えば:
>>> def failing_function():
... raise ValueError('Example error!')
>>> failing_function()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in failing_function
ValueError: Example error!
'Example error!'
というメッセージを含むValueError
れ'Example error!'
私たちのfailing_function()
によってfailing_function()
れました。これはインタープリタで実行されました。
コーリングコードは、コールが発生させることができるすべてのタイプの例外を処理することを選択できます。
>>> try:
... failing_function()
... except ValueError:
... print('Handled the error')
Handled the error
例外処理コードのexcept...
部分に例外オブジェクトを割り当てることによって、例外オブジェクトを保持することができます。
>>> try:
... failing_function()
... except ValueError as e:
... print('Caught exception', repr(e))
Caught exception ValueError('Example error!',)
組み込みのPython例外の完全なリストとその説明は、Pythonドキュメント( https://docs.python.org/3.5/library/exceptions.html)にあります 。そして、ここでは階層構造で配列された完全なリストがあります: Exception Hierarchy 。
カスタム例外の種類を作成する
Exception
から継承するクラスを作成する:
class FooException(Exception):
pass
try:
raise FooException("insert description here")
except FooException:
print("A FooException was raised.")
または別の例外タイプ
class NegativeError(ValueError):
pass
def foo(x):
# function that only accepts positive values of x
if x < 0:
raise NegativeError("Cannot process negative numbers")
... # rest of function body
try:
result = foo(int(input("Enter a positive integer: "))) # raw_input in Python 2.x
except NegativeError:
print("You entered a negative number!")
else:
print("The result was " + str(result))
すべてをキャッチしないでください!
それはしばしばすべてのException
をキャッチするために魅力Exception
ですが、
try:
very_difficult_function()
except Exception:
# log / try to reconnect / exit gratiously
finally:
print "The END"
# it runs no matter what execute.
あるいは、すべて( BaseException
とException
を含むすべての子を含む):
try:
even_more_difficult_function()
except:
pass # do whatever needed
ほとんどの場合、それは悪い習慣です。 SystemExit
、 KeyboardInterrupt
、 MemoryError
など、意図した以上のものを捕まえる可能性があります。通常は、通常のシステムエラーやロジックエラーとは異なる処理が行われます。また、内部コードが間違っている可能性があり、その状態から適切に回復する方法について明確な理解がないことを意味します。あなたがすべてのエラーをキャッチしている場合は、どのようなエラーが発生したのか、それを修正する方法はわかりません。
これはより一般的に「バグマスキング」と呼ばれ、避けるべきです。黙って失敗するか、悪化するのではなく、プログラムをクラッシュさせ、より深い実行レベルで失敗するようにしてください。 (それがトランザクションシステムであると想像してください)
通常、これらの構造体はプログラムの非常に外側のレベルで使用され、バグを修正できるようにエラーの詳細を記録するか、エラーをより具体的に扱うことができます。
複数の例外をキャッチする
1つは、同じ方法でキャッチして処理する例外タイプのタプルを作成することです。この例では、コードでKeyError
例外とAttributeError
例外が無視されます。
try:
d = {}
a = d[1]
b = d.non_existing_field
except (KeyError, AttributeError) as e:
print("A KeyError or an AttributeError exception has been caught.")
異なる例外をさまざまな方法で処理したい場合は、各タイプごとに別々の例外ブロックを用意することができます。この例では、引き続きKeyError
とAttributeError
キャッチしKeyError
が、例外をさまざまな方法で処理します。
try:
d = {}
a = d[1]
b = d.non_existing_field
except KeyError as e:
print("A KeyError has occurred. Exception message:", e)
except AttributeError as e:
print("An AttributeError has occurred. Exception message:", e)
例外処理の具体例
ユーザー入力
ユーザーが入力を介して番号をinput
。入力が数字であることを確認する必要があります。 try
/ except
を使用することができます:
while True:
try:
nb = int(input('Enter a number: '))
break
except ValueError:
print('This is not a number, try again.')
注:Python 2.xは代わりにraw_input
を使用します。関数input
はPython 2.xでは存在しinput
が、セマンティクスは異なります。上記の例では、 input
は2 + 2
ような式を受け取り、数値に評価されます。
入力を整数に変換できないValueError
は、 ValueError
が発生します。あなたはでそれをキャッチすることができますexcept
。例外が発生しなければ、 break
はループから飛び出します。ループの後、 nb
は整数を含む。
辞書
range(n)
ような連続した整数のリストを反復しているとし、特定の整数に遭遇したときに行うべきことに関する情報が入っている辞書d
リストを持っているとしたら、 d[i]
スキップします 。
d = [{7: 3}, {25: 9}, {38: 5}]
for i in range(len(d)):
do_stuff(i)
try:
dic = d[i]
i += dic[i]
except KeyError:
i += 1
存在しないキーの辞書から値を取得しようとすると、 KeyError
が発生します。
その他
elseブロックのコードは、 try
ブロック内のコードによって例外が発生していない場合にのみ実行されます。これは、例外がスローされた場合に実行したくないコードがいくつかあるが、そのコードによってスローされた例外を捕まえたくない場合に便利です。
例えば:
try:
data = {1: 'one', 2: 'two'}
print(data[1])
except KeyError as e:
print('key not found')
else:
raise ValueError()
# Output: one
# Output: ValueError
この種のelse:
elif
else節を開始するif
は、と組み合わせることはできません。下にインデントされている必要がある場合は、次のif
てelse:
:
try:
...
except ...:
...
else:
if ...:
...
elif ...:
...
else:
...