我有如下代碼塊:
try:
method()
except ErrorType1:
todo()
return
except ErrorType2 as e:
todo()
raise e
基本上對于這兩種錯誤型別,我需要先執行todo()
,然后是return
or raise e
。可以只寫todo()
一次嗎?我在考慮使用finally
,但不認為這真的有效。
uj5u.com熱心網友回復:
except
您可以在一個子句中捕獲兩個例外,執行todo
然后根據例外型別決定執行:
try:
method()
except (ErrorType1, ErrorType2) as e:
todo()
if isinstance(e, ErrorType1):
return
raise
注意 - 正如@ShadowRanger 在對問題的評論中指出的那樣 - 您應該只使用raise
重新引發現有例外,使用raise e
將引發它的第二個副本,從而導致回溯包括其raise e
上的行以及發生原始錯誤的行。
uj5u.com熱心網友回復:
如果您有一組必須作為例外處理的一部分執行的通用指令(封裝為一個函式或一系列函式) ,請考慮使用背景關系管理器來封裝通用位。以下兩個結果相同,盡管結構不同(一個使用try..finally
,另一個使用try..except
)。
from contextlib import contextmanager
@contextmanager
def context1(method):
print("starting context1")
completed = False
try:
yield method()
completed = True
finally:
if completed:
commit()
else:
rollback()
print("finished")
@contextmanager
def context2(method):
print("starting context2")
try:
yield method()
except Exception:
rollback()
raise
else:
commit()
print("finished")
后者將無法處理KeyboardInterrupt
子類 off 或其他例外BaseException
,因此對于某些用例,這并不完全理想,盡管它包含在問題套件中。第一個更多是對您似乎從未嘗試過使用這一事實的回應finally
,而只是簡單地認為它實際上不起作用,因此提供它以表明它可以用來實作您的目標(僅todo()
在問題中是如果失敗則通過使用布爾變數執行)。
在這兩種情況下,請注意公共控制流是如何完全封裝在背景關系管理器中的,并且使用非常簡單,因此所有獨特的額外情況都可以通過背景關系塊try..except
周圍的另一個塊來完成。with
try:
with context1(f) as result:
pass # or use the result to do something
except Exception: ...
# all the special unique cases be handled here.
要完成演示,下面是更多代碼;和函式我定義了以下內容commit
:rollback
def commit():
print("commit")
def rollback():
print("rollback")
現在為了測驗它,我定義了以下助手:
from functools import partial
class ErrorType1(Exception):
pass
class ErrorType2(Exception):
pass
def raise_e(e):
raise e
subject = [
object,
partial(raise_e, ErrorType1),
partial(raise_e, ErrorType2),
]
使用這樣定義的測驗(替換context1
為context2
其他演示):
for f in subject:
try:
with context1(f) as result:
print('done - got result %r' % result)
except ErrorType2:
print("ErrorType2 will be raised")
# raise # uncomment to actually re-raise the exception
except Exception as e:
print("Exception trapped: %r raised by %r" % (e, f))
請注意,以上兩者的輸出應該看起來像這樣(除了context1
vs context2
):
starting context1
done - got result <object object at 0x7f20ccd3e180>
commit
finished
starting context1
rollback
Exception trapped: ErrorType1() raised by functools.partial(<function raise_e at 0x7f20ccb30af0>, <class '__main__.ErrorType1'>)
starting context1
rollback
ErrorType2 will be raised
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/494840.html