编写自己的上下文管理器
上下文管理器是实现两个魔术方法 __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')