簡體   English   中英

如何從 python 中的“with”塊中引發異常

[英]How to raise an exception from within an 'with' block in python

我正在使用 sqlalchemy 創建事務。 我正在使用with來利用自動提交和回滾:

with session.begin():
    do_stuff()

如果引發異常,是否在自動回滾后傳播該異常?

如果在with語句的主體期間引發任何異常,則立即調用__exit__方法,並將該異常作為參數。 然后由__exit__決定是否已正確處理異常(通過返回真實值)或是否應在__exit__完成后重新引發(通過返回非真實值)。

SessionTransaction.__exit__只返回None ,這表明在with語句的主體中可能已經引發的任何異常都將再次引發。


請注意,由於任何 function 的“默認”返回值為None ,因此__exit__的默認行為是傳播任何異常。 用戶級代碼不應顯式調用__exit__或查看其返回值,因此您必須竭盡全力返回真實值並抑制表達式。


還要注意with語句語義的描述:

以下代碼:

 with EXPRESSION as TARGET: SUITE

在語義上等價於:

 manager = (EXPRESSION) enter = type(manager).__enter__ exit = type(manager).__exit__ value = enter(manager) hit_except = False try: TARGET = value SUITE except: hit_except = True if not exit(manager, *sys.exc_info()): raise finally: if not hit_except: exit(manager, None, None, None)

__exit__方法在兩個互斥條件之一下被調用:

  1. 引發了一個異常,在這種情況下,它在except子句中被調用。 如果它返回 false,則重新引發捕獲的異常。
  2. 沒有引發異常,在這種情況下,它在finally塊中被調用。 hit_except確保如果exit本身在except塊中引發異常,則不會調用兩次exit

你不應該做任何特別的事情。

使用with創建的上下文管理器大致相當於:

try:
    context initialization
    do_stuff()
finally:
    contact cleanup

except:子句不同, finally:不會阻止異常的傳播。 它執行語句,然后繼續傳播。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM