編寫自己的上下文管理器
上下文管理器是實現兩個魔術方法 __enter__()
和 __exit__()
的任何物件(儘管它也可以實現其他方法):
class AContextManager():
def __enter__(self):
print("Entered")
# optionally return an object
return "A-instance"
def __exit__(self, exc_type, exc_value, traceback):
print("Exited" + (" (with an exception)" if exc_type else ""))
# return True if you want to suppress the exception
如果上下文以異常退出,則有關該異常的資訊將作為三重 exc_type
,exc_value
,traceback
傳遞(這些變數與 sys.exc_info()
函式返回的變數相同)。如果上下文正常退出,那麼這三個論點都將是 None
。
如果發生異常並傳遞給 __exit__
方法,則該方法可以返回 True
以抑制異常,或者在 __exit__
函式結束時重新引發異常。
with AContextManager() as a:
print("a is %r" % a)
# Entered
# a is 'A-instance'
# Exited
with AContextManager() as a:
print("a is %d" % a)
# Entered
# Exited (with an exception)
# Traceback (most recent call last):
# File "<stdin>", line 2, in <module>
# TypeError: %d format: a number is required, not str
請注意,在第二個示例中,即使在 with 語句的主體中間發生異常,__exit__
處理程式仍會在異常傳播到外部作用域之前執行。
如果你只需要 __exit__
方法,則可以返回上下文管理器的例項:
class MyContextManager:
def __enter__(self):
return self
def __exit__(self):
print('something')