Open In App

Context Manager Using @contextmanager Decorator

Last Updated : 11 Aug, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

Decorators are very powerful and useful tool in Python since it allows programmers to modify the behavior of function or class. Decorators allow us to wrap another function in order to extend the behavior of wrapped function, without permanently modifying it.
 

Syntax: 

@decorator
def function(args):
    statements(s)

Example:  

Python3




# Python program to demonstrate
# decorators
 
def msg_decorator(func):
     
    # Inner function
    def msg_wrapper(msg):
        print("A decorated line:", func(msg))
         
    return msg_wrapper
 
# Using the decorator
@msg_decorator
def print_name(name):
    return name
 
print_name("Pooventhiran")


Output: 

A decorated line: Pooventhiran

 

In this example, whenever print_name() is called, first, msg_decorator is called with print_name as the argument. Inside msg_decorator, msg_wrapper is returned which simply calls whichever function passed to msg_decorator with the arguments passed to it. Though this example is simple, these are so powerful in actual usecases like checking for boundary/special conditions, pre-processing, etc.
Note: For more information refer to Decorators in Python.
 

Context Manager

Context Managers are Python’s resource managers. In most cases, we use files as resources (a simple resource). We often don’t care about closing the files at the end of execution. This is a bad coding practice and also this causes issues when too many files are opened, or when the program is terminated with failure as the resource is not properly released. Context managers are the rescue for this issue by automatically managing resources. In Python, the with keyword is used.
 

Example:

Python3




# Python program to demonstrate
# Context Manager
 
with open('testfile.txt') as in_file:
    print(''.join(in_file.readlines()))


In the example shown above, the file used is managed by ContextManager itself as it closes the file even if the program fails. This context manager feature can also be built into our programs. The user need to ensure that the class has the methods: __enter__() and __exit__(). Let’s look at a template with these special methods.
 

Python3




# Python program creating a
# context manager
   
class ContextManager():
    def __init__(self):
        print('init method called')
           
    def __enter__(self):
        print('enter method called')
        return self
       
    def __exit__(self, exc_type, exc_value, exc_traceback):
        print('exit method called')
   
# Driver code
with ContextManager() as manager:
    print('with statement block')
        


Output:
 

init method called
enter method called
with statement block
exit method called

In the above code, __enter__ will be executed when control enters with and __exit__, when control leaves with clause. We can simply make any function as a context manager with the help of contextlib.contextmanager decorator without having to write a separate class or __enter__ and __exit__ functions.
 

Using @contextmanager

We have to use contextlib.contextmanager to decorate a generator function which yields exactly once. Everything before yield is considered to be __enter__ section and everything after, to be __exit__ section. The generator function should yield the resource. 
 

Example: Let’s rewrite the above example with this decorator 

Python3




# Python program for creating a
# context manager using @contextmanager
# decorator
 
from contextlib import contextmanager
 
@contextmanager
def ContextManager():
     
    # Before yield as the enter method
    print("Enter method called")
    yield
     
    # After yield as the exit method
    print("Exit method called")
 
with ContextManager() as manager:
    print('with statement block')


Output:

Enter method called
with statement block
Exit method called 


Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads