A context manager is any object that implements two magic methods __enter__()
and __exit__()
(although it can implement other methods as well):
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
If the context exits with an exception, the information about that exception will be passed as a triple exc_type
, exc_value
, traceback
(these are the same variables as returned by the sys.exc_info()
function). If the context exits normally, all three of these arguments will be None
.
If an exception occurs and is passed to the __exit__
method, the method can return True
in order to suppress the exception, or the exception will be re-raised at the end of the __exit__
function.
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
Note that in the second example even though an exception occurs in the middle of the body of the with-statement, the __exit__
handler still gets executed, before the exception propagates to the outer scope.
If you only need an __exit__
method, you can return the instance of the context manager:
class MyContextManager:
def __enter__(self):
return self
def __exit__(self):
print('something')