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
withstatement stores the__exit__method of theBananaclass. - It calls the
__enter__method of theBananaclass. - 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
withstatement 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
yieldkeyword. 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
contextmanagerdecorator returns the generator wrapped by theGeneratorContextManagerobject. - The
GeneratorContextManageris assigned to thebananafunction. Therefore, when we later call thebananafunction, we are actually calling theGeneratorContextManagerobject.