Fundamentals 5 min read

Using Python Context Managers to Write More Pythonic Code

This article explains the concept of Python context managers, demonstrates how the with statement simplifies resource handling compared to manual open/close patterns, and shows how defining __enter__ and __exit__ methods enables cleaner code, testing, and error handling.

Python Programming Learning Circle
Python Programming Learning Circle
Python Programming Learning Circle
Using Python Context Managers to Write More Pythonic Code

In the Python community, writing "Pythonic" code means leveraging language features effectively, and context managers are a key tool for achieving this style.

Raymond Hettinger’s 2015 PyCon talk "Beyond PEP 8" highlighted the importance of context managers, and this article builds on that insight.

A context manager is an object that defines the runtime context for a with statement, handling entry and exit automatically.

Typical usage when opening a file:

with open('filename.txt', 'r') as datafile:
    for line in datafile:
        print(line)

Without a context manager, the same task requires explicit close calls:

datafile = open('filename.txt', 'r')
for line in datafile:
    print(line)
datafile.close()

By using a context manager, the file is closed automatically at the end of the block, improving readability and safety.

Any class can become a context manager by implementing __enter__ and __exit__ methods; __enter__ runs when the block starts, and __exit__ runs when it finishes.

Hettinger’s example wraps network code in a context manager:

from nettools import NetworkElement

with NetworkElement('171.0.2.45') as ne:
    for route in ne.routing_table:
        print('%15s -> %s' % (route.name, route.ipaddr))

The NetworkElement class defines only the essential methods:

class NetworkElement(object):
    def __enter__(self):
        return self
    def __exit__(self, exctype, excinst, exctb):
        if exctype == NetworkElementError:
            logging.exception('No routing table found')
            self.oldne.cleanup('rollback')
        else:
            self.oldne.cleanup('commit')
        self.oldne.disconnect()

Context managers are also handy for testing, such as asserting exceptions with pytest:

import pytest

def test_zero_division():
    with pytest.raises(ZeroDivisionError):
        1 / 0

And for mocking with unittest.mock:

from unittest.mock import patch
with patch('Class.method', mocked_method):
    # run test code

Overall, context managers enable concise resource management, validation, cleanup, and error handling, allowing developers to focus on core logic.

PythonTestingException HandlingContext Managerwith-statementpythonic
Python Programming Learning Circle
Written by

Python Programming Learning Circle

A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.