Python Utilities for with-statement contexts (contextlib)


contextlib module of Python's standard library defines ContextManager class whose object properly manages the resources within a program. Python has with keyword that works with context managers. The file object (which is returned by the built-in open() function) supports ContextManager API. Hence we often find with keyword used while working with files.

Following code block opens a file and writes some data in it. After the operation is over, the file is closed, failing which file descriptor is likely to leak leading to file corruption.

f = open("file.txt","w")
f.write("hello world")
f.close()

However same file operation is done using file's context manager capability using following syntax.

with open("file.txt","w") as f:
f.write("hello world")
print ("file is closed")

As mentioned above, the file object implements ContextManager. It is enabled by with keyword. The with block contains statements to be processed for the file object. As soon as with block is over, the file object is automatically closed (The close() method needn't be called explicitly). Any object that is subjected to with block will be active only inside the block and will be immediately disposed at its end.

The ContextManager class has two essential methods __enter__() and __exit__()

__enter__() − will be called when with block starts. It indicates that program has entered the runtime context related to this object.

__exit__() − is called when with block is over. It indicates that program exits the runtime context related to this object.

The file object too possesses these two methods as can be confirmed by following interpreter session.

>>> f = open("file.txt","w")
>>> f.__enter__()
<_io.TextIOWrapper name = 'file.txt' mode = 'w' encoding = 'cp1252'>
>>> f.write("hello world")
11
>>> f.__exit__()
>>> f.write("hello world")
Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
f.write("hello world")
ValueError: I/O operation on closed file.

When __exit__() method is called, the file is closed. That's why the ValueError appears as we try to write some data to the file after it is closed.

Given below is a more generalized use of contextManager. First we define a class with __enter__() and __exit__() methods and enable contextManager for its object using with statement.

import contextlib
class WithExample:
   def __init__(self):
      print ("object initialized")
   def __enter__(self):
      print ("entered context")
   def __exit__(self, *args):
      print ("exited context")
with WithExample() as w:
print ('this is a contextlib example')
print ('used by with statement')
print ('end of with block')

The output shows that as soon as the with block starts, the __enter__() method is executed. The statements within the block get processed. When the block is over, the __exit__() method to is automatically called.

object initialized
entered context
this is a contextlib example
used by with statement
exited context
end of with block

The contextlib module has @contextmanager decorator with the help of which we can write a generator based factory function to automatically support with statement. The file object's context management with decorator is as follows −

from contextlib import contextmanager
@contextmanager
def openfile(name):
   try:
      f = open(name, 'w')
      yield f
   finally:
      f.close()
with openfile(file.txt') as f:
f.write('hello world')
print ('file is closed')

The ContextManager thus is a very useful feature of Python for effective management of resources in a program.

Updated on: 27-Jun-2020

286 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements