例外を再度発生させたい場合は、それぞれのraise
ブロックで引数なしでexcept
を使用するだけです。しかし、次のようなネストされた式が与えられた場合
try:
something()
except SomeError as e:
try:
plan_B()
except AlsoFailsError:
raise e # I'd like to raise the SomeError as if plan_B()
# didn't raise the AlsoFailsError
スタックトレースを中断せずにSomeError
を再レイズするにはどうすればよいですか?この場合、raise
だけで最新のAlsoFailsError
が再レイズされます。または、この問題を回避するためにコードをどのようにリファクタリングできますか?
例外のタイプ、値、およびトレースバックをローカル変数に保存し、 引数形式のraise
を使用できます。
try:
something()
except SomeError:
t, v, tb = sys.exc_info()
try:
plan_B()
except AlsoFailsError:
raise t, v, tb
Python 3では、トレースバックは例外に保存されるため、raise e
は(ほとんど)正しいことを行います:
try:
something()
except SomeError as e:
try:
plan_B()
except AlsoFailsError:
raise e
上記の唯一の問題は、SomeError
の処理中にAlsoFailsError
が発生したことを示すわずかに誤解を招くトレースバックを生成することです(raise e
内部except AlsoFailsError
)、実際にはほぼ正反対が発生しました-AlsoFailsError
からの回復を試みている間にSomeError
を処理しました。この動作を無効にし、AlsoFailsError
に言及しないトレースバックを取得するには、raise e
with raise e from None
。
承認されたソリューション が正しい場合でも、Python2 + 3ソリューションを持つ Six ライブラリを指すのは良いことです、 six.reraise
を使用します。
six。reraise(exc_type、exc_value、 exc_traceback=なし)
おそらく別のトレースバックを使用して、例外をリレイズします。 [...]
だから、あなたは書くことができます:
import six
try:
something()
except SomeError:
t, v, tb = sys.exc_info()
try:
plan_B()
except AlsoFailsError:
six.reraise(t, v, tb)
Drew McGowenの提案 に従いますが、一般的なケース(戻り値s
が存在する場合)を処理する場合、 ser4815162342の答え の代わりになります:
try:
s = something()
except SomeError as e:
def wrapped_plan_B():
try:
return False, plan_B()
except:
return True, None
failed, s = wrapped_plan_B()
if failed:
raise
とにかくPython 3.5+はトレースバック情報をエラーに添付するため、個別に保存する必要はなくなりました。
>>> def f():
... try:
... raise SyntaxError
... except Exception as e:
... err = e
... try:
... raise AttributeError
... except Exception as e1:
... raise err from None
>>> f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 9, in f
File "<stdin>", line 3, in f
SyntaxError: None
>>>