python – 在上下文管理器中捕獲異常__enter __()
即使在__enter __()中有異常,也可以確保__exit __()方法被呼叫?
>>> class TstContx(object): ...def __enter__(self): ...raise Exception('Oops in __enter__') ... ...def __exit__(self, e_typ, e_val, trcbak): ...print "This isn't running" ... >>> with TstContx(): ...pass ... Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in __enter__ Exception: Oops in __enter__ >>>
編輯
這是儘可能接近我可以得到…
class TstContx(object): def __enter__(self): try: # __enter__ code except Exception as e self.init_exc = e return self def __exit__(self, e_typ, e_val, trcbak): if all((e_typ, e_val, trcbak)): raise e_typ, e_val, trcbak # __exit__ code with TstContx() as tc: if hasattr(tc, 'init_exc'): raise tc.init_exc # code in context
在後視中,情景管理器可能不是最好的設計決策
喜歡這個:
import sys class Context(object): def __enter__(self): try: raise Exception("Oops in __enter__") except: # Swallow exception if __exit__ returns a True value if self.__exit__(*sys.exc_info()): pass else: raise def __exit__(self, e_typ, e_val, trcbak): print "Now it's running" with Context(): pass
要讓程式繼續執行,而不執行上下文塊,您需要檢查上下文塊中的上下文物件,並且只有在__enter__成功時才能執行重要的操作.
class Context(object): def __init__(self): self.enter_ok = True def __enter__(self): try: raise Exception("Oops in __enter__") except: if self.__exit__(*sys.exc_info()): self.enter_ok = False else: raise return self def __exit__(self, e_typ, e_val, trcbak): print "Now this runs twice" return True with Context() as c: if c.enter_ok: print "Only runs if enter succeeded" print "Execution continues"
據我所知,您無法完全跳過該塊.並注意到這個上下文現在吞噬了它中的所有異常.如果您希望在__enter__成功時不要吞下異常,請在__exit__中檢查self.enter_ok,如果為True,則返回False.
http://stackoverflow.com/questions/13074847/catching-exception-in-context-manager-enter