Skip to content

Python Context Manager

Python Context Manager

While Python's context managers are widely used, few understand the purpose behind their use. These statements, commonly used with reading and writing files, assist the application in conserving system memory and improve resource management by ensuring specific resources are only in use for certain processes.

The with statement

A context manager is an object that is notified when a context (a block of code) starts and ends. You commonly use one with the with statement. It takes care of the notifying.

For example, file objects are context managers. When a context ends, the file object is closed automatically:

>>> with open(filename) as f:
...     file_contents = f.read()
...
>>> # the open_file object has automatically been closed.

Anything that ends execution of the block causes the context manager's exit method to be called. This includes exceptions, and can be useful when an error causes you to prematurely exit an open file or connection. Exiting a script without properly closing files/connections is a bad idea, that may cause data loss or other problems. By using a context manager, you can ensure that precautions are always taken to prevent damage or loss in this way.

Writing your own context manager

It is also possible to write a context manager using generator syntax thanks to the contextlib.contextmanager decorator:

>>> import contextlib
>>> @contextlib.contextmanager
... def context_manager(num):
...     print('Enter')
...     yield num + 1
...     print('Exit')
...
>>> with context_manager(2) as cm:
...     # the following instructions are run when
...     # the 'yield' point of the context manager is
...     # reached. 'cm' will have the value that was yielded
...     print('Right in the middle with cm = {}'.format(cm))
...
# Enter
# Right in the middle with cm = 3
# Exit

Class based context manager

You can define class based context manager. The key methods are __enter__ and __exit__

class ContextManager:
    def __enter__(self, *args, **kwargs):
        print("--enter--")

    def __exit__(self, *args):
        print("--exit--")


with ContextManager():
    print("test")
#--enter--
#test
#--exit--