Delving into Python Decorators: Part 4
This is the final part of the four-part series on decorators in Python. Part one, part two, and part three can be found here.
In part one, we discussed how decorators work, along with when and why to use them. In part two, we covered how to use decorators as a basic way of debugging functions, and in part three, we used decorators to rate-limit (or slow down) functions.
In this article, we’re going to review how Python uses decorators in the standard library. We will be reviewing the module contextlib
[1], from the Python standard library. The contextlib
module has a few functionalities, but we will be using it to build a context manager[2]. First, review the code below:
This code block opens the text_file
file, reads from it, and then closes it. Closing a resource is important because failing to do so leads to memory leakage[3]. Memory leaks are encountered in Python in a few different ways, but the method we will discuss in this article is going to be opening a file and not closing it afterward. By forgetting to do this, you cause a memory leak. That's why so many programmers use the with
keyword since it automatically closes the file after it's done, and frees up the resources it was using. It's important to remember that the with
keyword is an example of a context manager. It is used to manage resources when opening a file. See below:
This is a more efficient way to read a file since you don’t have to manually close it every time. However, this can be further improved. We can use contextlib
to build a custom context manager. See below:
As done in previous parts, let’s break this down into simpler steps.
Step 1: Import statements
We only have 2 modules we’re importing from: colorama
and contextlib
.
colorama
makes terminal output colorful, and it requires apip
install if you have not installed it before. To do so, typepip3 install colorama
in your terminal. If you've been following along with the series, you probably havecolorama
installed from the previous decorator articles.
Step 2: context_manager
Decorator
The context_manager
decorator turns the decorated function into a context manager, as seen with the my_file_manager
function. contextlib
uses this to notify Python that this is a context manager, so without this, you would get an error that says that the context manager does not implement an __enter__
[4] or __exit__
[5] method. These two methods are integral to creating a context manager, and the contextlib
module includes them in the decorated function.
Step 3: Inside my_file_manager
This context manager has multiple uses. You can use it to read from, write to, and append to files. Today we will be using the write and read functions. The mode is passed through the arguments for my_file_manager
function, and it is used to determine the value of a variable called type_mode
. This variable elaborates on what the my_file_manager
function is currently doing and then is used in the final print statement, to show what the function is actually doing. We use a try/finally
[6] block, within which we have a yield
[7] statement. The yield
statement is usually used to return a sequence of values - so it doesn't quit the function after returning a value, whereas the return
statement returns a singular value and quits the function. We use the yield
statement because we have more code after it, so we need to come back to the my_file_manager
function. Moving onto the finally
block, we have a print statement showing what operation was performed, and the file closing statement.
Step 4: Using the context manager
Now, we can use our context manager to interact with text files.
First, let’s look at how the file manager handles writing to a file. We can make a simple with
statement using our context manager to write to a text file.
Our terminal output:
By executing this block of code, you should see a new text file in your current working directory called ‘text-file.txt’. If you open it, you see whatever you set as your output_string
variable.
Now, let’s look at reading from a text file.
This with
statement reads the contents of the previously created text-file.txt file. It then prints out the text in the file, which was also created with the previous statement. Now for our terminal output:
Great, it works!
In short, we’ve successfully read from a text file, using our own custom file manager. This file manager is scalable and can be changed to work with a database, or other resources. We learned how Python uses decorators to make context managers with the contextlib
module. We worked a bit more with colorama
and found another use for decorators in Python.
If you’ve been following along with this series, you’ve learned a good amount of material about Python decorators. In article one, we learned how to use decorators in our code. In article two, we built a basic logging function, used to see how long it took for the decorated function to run while learning about the colorama and time modules from the standard library. In article three, we used decorators to slow down (or rate-limit) code, along with utilizing the random, funcTools, and sys modules from the standard library. In this article, we used decorators to create a context manager, while using the contextlib module. Pat yourself on the back for delving deeper into one of Python’s most helpful features.w
Thanks for reading, and I hope you’ve enjoyed reading this series as much as I enjoyed writing it. If you’ve enjoyed my writing, please consider subscribing so you can see my new series as soon as they’re out.