We’ve learned that we can create our own context managers using the class-based method, but there’s an even simpler way of creating context managers. We can use a built-in Python module called
contextlib module allows for the creation of a context manager with the use of a generator function (a function that uses
yield instead of
return) and the contextlib decorator -
@contextmanager. Instead of creating a class and definining
__exit__ methods, we can use a simple function!
There are a few steps in the setup so let’s take it slow and break down each step. First, we will need to import the built-in module into our script and grab the
from contextlib import contextmanager
Once we have successfully imported the module, we can automatically use the
@contextmanager decorator to wrap a simple generator function:
from contextlib import contextmanager @contextmanager def open_file_contextlib(file, mode): opened_file = open(file, mode) try: yield opened_file finally: opened_file.close()
We are doing a few things here:
- We have written a generator function called
open_file_contextlibwith the expectation that it will take in two arguments, a file and a mode.
- We then use the built-in
open()function to open the file (that we received as an argument) and save it to a variable called
- The function then will attempt (via a
yieldthe opened file and complete whatever code we pass when we use it in conjunction with the
withstatement. More on this in a bit!
- Lastly the resource (file) will be closed once all the code is done being executed.
If we think about this structure in sections relative to the class-based approach, it essentially breaks down into this:
@contextmanager def generator_function(<parameters>): <setup section - equivalent to __enter__ > try: yield <value> finally: <cleanup section - equivalent to __exit__ >
Once we have created this function and denoted it as a context manager using the
@contextmanager decorator, we can immediately use it like before in a
with open_file_contextlib('file.txt', 'w') as opened_file: opened_file.write('We just made a context manager using contexlib')
Following this pattern of creating context managers allows us to quickly convert generator functions to become context managers without the need to create any extra classes. Now, let’s remake our poem context manager following this pattern!
Let’s create our
PoemFiles context manager from previous exercises. First, import
Now, let’s create a generator function called
poem_files that has two parameters
mode. The function should do two things:
- Open the file using
modeparameters, and save the result to a variable called
Don’t forget to decorate it with the
Next, we will have to create the
finally structure. Inside of the function write the
try clause, and inside of it use the
yield keyword to yield the
Now, let’s finish the
finally block by writing a
finally clause that does two things:
Uncomment and run the
with statement below your script.