python 36 lines · 6 steps

Writing context managers in Python

Two classes show how __enter__ and __exit__ guarantee setup and teardown, even when exceptions strike.

Explained by highlit
1class FileManager:
2 """A context manager that safely opens and closes a file."""
3 
4 def __init__(self, path, mode="r"):
5 self.path = path
6 self.mode = mode
7 self.file = None
8 
9 def __enter__(self):
10 self.file = open(self.path, self.mode)
11 return self.file
12 
13 def __exit__(self, exc_type, exc_value, traceback):
14 if self.file:
15 self.file.close()
16 # Returning False lets any exception propagate;
17 # returning True would suppress it.
18 return False
19 
20 
21class Transaction:
22 """Commits on success, rolls back if an exception occurred."""
23 
24 def __init__(self, connection):
25 self.connection = connection
26 
27 def __enter__(self):
28 self.connection.begin()
29 return self.connection
30 
31 def __exit__(self, exc_type, exc_value, traceback):
32 if exc_type is None:
33 self.connection.commit()
34 else:
35 self.connection.rollback()
36 return False
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Implementing __enter__ and __exit__ makes any object usable in a with-block.
  2. 2__exit__ always runs, which is what makes it the right place for cleanup.
  3. 3The return value of __exit__ decides whether an exception is swallowed or propagated.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Writing context managers in Python — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code