What is a context manager in Python and how to create your own context manager?
If you don,t know what is context manager the don’t worry you will know it clearly after you finish this article
The main principle behind writing a context manager is that you’re writing code that’s meant to surround a block of statements as defined by the use of the with a statement. Context managers allow you to allocate and release resources precisely when you want to. The most widely used example of context managers is the with
statement. Suppose you have two related operations which you’d like to execute as a pair, with a block of code in between. Context managers allow you to do specifically that. For example:
1
2
with open('cornsite.txt', 'wt') as fk:
fk.write('cornhub.com')
The above code opens the file called “cornsite.txt” and writes some data and closes it. If an error occurs while writing the data to the file, it tries to close it. It will look something like this if we don,t use context manager:
1
2
3
4
5
file = open('cornsite.txt', 'wt')
try:
file.write('cornhub.com!')
finally:
file.close()
The main advantage of using a with
statement is that it makes sure our file is closed without paying attention to how the nested block exits.
Now let’s see how can we create our own context manager
Accomplishing context manager as through class :
To create a context manager with the help of class we have to use __enter__
and __exit__
dunder method. The enter() returns the resource that needs to be managed and the exit() does not return anything but performs the cleanup operations. let,s make our own file opening context manager :
1
2
3
4
5
6
7
class Banana(object):
def __init__(self, file_name, method):
self.file_object = open(file_name, method)
def __enter__(self):
return self.file_object
def __exit__(self, type, value, traceback):
self.file_object.close()
Just by defining __enter__
and __exit__
methods we can use our new class Banana in a with
statement
1
2
with Banana('message.txt', 'w') as fk:
fk.write('Send Dudes!😇')
Congratulation you just created your first context manager
Let’s see what is happening underneath the hood:
- The
with
statement stores the__exit__
method of theBanana
class. - It calls the
__enter__
method of theBanana
class. - The
__enter__
method opens the file and returns it. - The opened file handle is passed to
fk
. - We write to the file using
.write()
. - The
with
statement calls the stored__exit__
method. - The
__exit__
method closes the file.
Now Accomplishing context manager as through Generator
Creating context managers the traditional way, by writing a class with __enter__
and __exit__
methods are not difficult. But sometimes it is more overhead than you need just to manage a trivial bit of context. For that Python has a contextlib module for this very purpose. Instead of a class, we can implement a Context Manager using a generator function. Let’s see a basic, useless(as you) example:
1
2
3
4
5
6
7
8
from contextlib import contextmanager
@contextmanager
def banana(name):
f = open(name, 'w')
try:
yield f
finally:
f.close()
Now let’s use this
1
2
with banana('potato.txt') as f:
f.write('sexy kto mah 123!')
Booom its working lets discuss a little how it’s working
- Python encounters the
yield
keyword. Due to this, it creates a generator instead of a normal function. - Due to the decoration, contextmanager is called with the function name (
banana
) as its argument. - The
contextmanager
decorator returns the generator wrapped by theGeneratorContextManager
object. - The
GeneratorContextManager
is assigned to thebanana
function. Therefore, when we later call thebanana
function, we are actually calling theGeneratorContextManager
object.