Python context managers are special constructs that represent blocks of code that are enclosed in the with statement. The with statement creates a block using the context manager protocol.
Usage example #
The simplest function that uses this protocol is the
open() function. Every time we open a file, we need to close it, which would flush the output to disk (in fact, Python calls the close () method automatically, but its explicit use is a good way).
fp = open("./file.txt", "w") fp.write("Hello, World") fp.close()
That each time you do not call the
close() method, we can use the context manager of the
open() function, which will automatically close the file after exiting the block:
with open("./file.txt", "w") as fp: fp.write("Hello, World")
We do not need to call the close method each time, which would flush the data into a file. The context manager is used to perform any actions before entering the block and after exiting it. But the functionality of context managers does not end there. In many programming languages, destructors are used for such tasks. But in Python if an object is used somewhere else then there is no guarantee that the destructor will be called, since the
__del__ method is called only if all references to the object have been exhausted:
In : class Hello: ...: def __del__(self): ...: print 'destructor' ...: In : f = Hello() In : c = Hello() In : e = Hello() In : del e destructor In : del c destructor In : c = f In : e = f In : del f # Destructor is not called
We will solve this problem through context managers:
In : class Hello: ...: def __del__(self): ...: print u'destructor' ...: def __enter__(self): ...: print u'enterng to block' ...: def __exit__(self, exp_type, exp_value, traceback): ...: print u'exiting from block' ...: In : f = Hello() In : c = f In : e = f In : d = f In : del d In : del e In : del c In : del f # <- destructor was called when all references to the object was deleted desctructor
Now let's call the context manager:
In : with Hello(): ....: print u'my code' ....: entering to block my code exiting from block destructor
We saw that there was a guaranteed exit from the block after the execution of our code.