PEP 343 - The “with” statement
https://docs.python.org/3/library/stdtypes.html#context-manager-types
https://docs.python.org/3/reference/datamodel.html#with-statement-context-managers
https://docs.python.org/3/library/contextlib.html
Python’s 'with' statement supports the concept of a runtime context defined by a context manager. This is implemented using a pair of methods that allow user-defined classes to define a runtime context that is entered before the statement body is executed (__enter__) and exited when the statement ends (__exit__).
Typical uses of context managers include saving and restoring various kinds of global state, locking and unlocking resources, closing opened files, etc.
The 'with' statement allows common 'try + except + finally' usage patterns to be encapsulated for convenient reuse.
# Syntax.
with expression as target: # 'as target' is optional
statements
with A() as a, B() as b:
statements
# is semantically equivalent to nested 'with' statements:
with A() as a:
with B() as b:
statements
with open('book.txt', 'r') as infile: # infile will be closed
text = infile.read()
with open('results.txt', 'w') as outfile: # outfile will be closed
outfile.write("message\n")
class ContextManager:
def __init__(self): # optional
pass
def message(self, argument):
print("processing {}".format(argument))
def __enter__(self):
print("start with")
return self # or something else;
# the return value will be assigned to 'target'
def __exit__(self, exception_type, exception_value, exception_traceback):
if exception_type is None: # (None, None, None) is supplied to __exit__
print("normal exit") # no exception
# put cleanup code here
return True
else: # the exception type, value, traceback are supplied to __exit__
print("exception raised is {}".format(exception_type))
# put cleanup code here
return False # exception is reraised
# return True # exception is suppressed
# Usage.
with ContextManager() as context:
context.message("test 1")
print("point reached")
with ContextManager() as context:
context.message("test 2")
raise TypeError
print("point not reached")
print("after with statements")
# Results.
# start with
# processing test 1
# point reached
# normal exit
# start with
# processing test 2
# exception raised is <class 'TypeError'>