What is the contextlib module?

svg viewer

Overview

The contextlib module of Python’s standard library provides utilities for resource allocation to the with statement.

The with statement in Python is used for resource management and exception handling. Therefore, it serves as a good Context Managerallocates and releases resources during the execution of a python program. When the code reaches a with statement, it allocates resources temporarily. As soon as the with statement block finishes, all the resources initially consumed by with are released.

There are three functions provided by the contextlib module:

  1. contextmanager(func)
  2. nested(mgr1[, mgr2[, …]])
  3. closing(thing)

contextmanager(func)

A Context Manager requires two basic functions: __enter__() and __exit__(). You can implement a context manager in a class by writing __enter__() and __exit__() functions. By defining these functions in a class, we can use it alongside the with statement to provide optimal resource allocation. Take a look at the following code:

class myFileHandler():
def __init__(self, fname, method):
print("I'm in contructor")
self.file_obj = open(fname, method)
def __enter__(self):
print("I'm in ENTER block")
return self.file_obj
def __exit__(self, type, value, traceback):
print("I'm in EXIT block")
self.file_obj.close()
with myFileHandler("this_file.txt", "w") as example:
######### read write statements #########
print("I'm in WITH block")
pass

The with statement calls our class myFileHandler(). The __enter__() method calls the constructor, opens a file using the parameters passed, and returns the file object to the with statement, which then assigns it to example. Then, the statements in the with block are executed. As soon as it exits the with block, the __exit__() method is invoked, and the process is gracefully terminated.

The entire process above can be replicated using the contextmanager(func) utility with the need for separate __enter__() and __exit__() methods. Take a look at the following code:

from contextlib import contextmanager
@contextmanager
def thisFunc(fname, method):
print("This is the implicit ENTER block")
my_file = open(fname, method)
yield my_file
print("This is the implicit EXIT block")
my_file.close()
with thisFunc("this_file.txt", "w") as example:
######### read write statements #########
print("I'm in WITH block")
pass

It is fair to say that using the contextmanager(func) (as a decorator) makes the code more readable and easier to understand. The decorated contextmanager(func) has three sections:

  • The section above the yield statement does what an __enter__() method does.
  • The yield statement returns an iterator to the target in the with statements as clause - example. At this stage, the control is passed to the with statement.
  • The section below the yield statement does what an __exit__() method does.

nested(mgr1[, mgr2[, …]])

The contextlib module provides us with a utility to use when we need to call multiple functions with the with statement. The nested() function makes our lives easier in this scenario. Consider the following nested with statements:

with X as file_1:
    with Y as file_2:
        with Z as file_3:
            # statements for file_1, file_2, and file_3

The nested function contracts the code above into one line

from contextlib import nested

with nested(X, Y, Z) as (file_1, file_2, file_3):
    # statements for file_1, file_2, and file_3

If an __exit__() method of a Context Manager (X, Y, or Z) suppresses an exception, then the exception will not be passed to all the outer Context Managers. Similarly, If an __exit__() method of a Context Manager (X, Y, or Z) raises an exception, then the exception will be passed to all the outer Context Managers.

closing(thing)

The closing(thing) method returns a Context Manager that closes thing upon completion of the with block. For example:

from contextlib import contextmanager
import socket

@contextmanager
def closing(thing):
    try:
        thing.connect("localhost", 8333)
        yield thing
    finally:
        thing.close()

sock = socket.socket()
with closing(sock) as my_sock:
    my_sock.listen()

The code above sends a socket object to the decorated Context Manager closing(thing). The Context Manager establishes a connection and returns the thing object back to the with statement. When the with statement block commences, the socket object is closed.

The closing(thing) function of contextlib module lets you write the code above like this:

from contextlib import closing
import socket

with closing(socket.socket()) as my_sock:
    my_sock.listen()

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved