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
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'>