次のコードで2番目(A
)が発生した場合、最初の例外(B
)はどうなりますか?
class A(Exception): pass
class B(Exception): pass
try:
try:
raise A('first')
finally:
raise B('second')
except X as c:
print(c)
X = A
で実行すると、次のようになります:
トレースバック(最後の最後の呼び出し): ファイル "raising_more_exceptions.py"、6行目 raise A( 'first') __ main __。A:first 上記の例外の処理中に、別の例外が発生しました: トレースバック(最後の最後の呼び出し): ファイル「raising_more_exceptions.py」、8行目 でB( 'second')を上げる __ main __。B:秒
しかし、X = B
の場合:
第二
この質問は、例外処理がPython 2とはまったく異なるため、Python 3に特に対処します。
質問3に回答すると、以下を使用できます。
raise B('second') from None
例外A
トレースバックが削除されます。
Traceback (most recent call last):
File "raising_more_exceptions.py", line 8, in
raise B('second')
__main__.B: second
'causing'例外は、最後の例外ハンドラーでc .__ context__として利用できます。 Pythonはこの情報を使用して、より有用なトレースバックをレンダリングします。Python 2.xでは、元の例外は失われていました。これはPython 3のみ。
通常、これを使用して一貫性のある例外をスローし、元の例外にアクセス可能なままにします(例外ハンドラーから自動的に発生するのは非常にクールですが、私は知りませんでした!):
try:
do_something_involving_http()
except (URLError, socket.timeout) as ex:
raise MyError('Network error') from ex
詳細情報(およびその他の非常に役立つこと)をここに: http://docs.python.org/3.3/library/exceptions.html
Pythonの例外処理は、一度に1つの例外のみを処理します。ただし、例外オブジェクトには、他のすべてと同じ変数ルールとガベージコレクションが適用されます。したがって、別の例外が発生した場合でも、例外オブジェクトを変数に保存しておけば、後で処理できます。
あなたの場合、「finally」ステートメント中に例外が発生すると、Python 3は、2番目の例外の前に最初の例外のトレースバックを出力します。
より一般的なケースは、明示的な例外処理中に例外を発生させたい場合です。その後、次の例外で例外を「保存」できます。パラメータとして渡すだけです:
>>> class A(Exception):
... pass
...
>>> class B(Exception):
... pass
...
>>> try:
... try:
... raise A('first')
... except A as e:
... raise B('second', e)
... except Exception as c:
... print(c.args[1])
...
first
ご覧のとおり、元の例外にアクセスできます。
私はあなたの質問に答えるためのすべての要素が既存の答えに既にあると信じています。組み合わせて詳しく説明します。
行番号の参照を提供するために質問のコードを繰り返しましょう。
1 class A(Exception): pass
2 class B(Exception): pass
3
4 try:
5 try:
6 raise A('first')
7 finally:
8 raise B('second')
9 except X as c:
10 print(c)
質問に答えるには:
最初の例外A
は6行目で発生します。7行目のfinally
句はalwaysすぐに実行されますtry
ブロック(5行目から6行目)は、正常に完了したために、または例外が発生したために残されているかどうかに関係なく、残されます。 finally
句の実行中に、8行目で別の例外B
が発生します。レナートとイグナツィオが指摘したように、追跡できるのは、最近発生した例外を1つだけです。したがって、B
が発生するとすぐに、全体のtry
ブロック(行4〜8)が終了し、例外B
がexcept
によってキャッチされます一致する場合、9行目のステートメント(X
がB
の場合)。
うまくいけば、これが1の説明から明らかになったことを願っています。ただし、内部/下位/最初の例外をキャッチできます。少し修正したレナートの答えをマージするために、両方をキャッチする方法を次に示します。
class A(Exception): pass
class B(Exception): pass
try:
try:
raise A('first')
except A as e:
raise B('second', e)
except Exception as c:
print(c)
出力は次のとおりです。
('second', A('first',))
Lennartの例では、この質問に対する解決策はexcept A as e
ここで、内部/下位/最初の例外がキャッチされ、変数e
に格納されます。
例外をキャッチするタイミング、無視するタイミング、再発生するタイミングの一般的な直感として、多分 この質問とAlex Martelliの答え ヘルプ。