Function-Based Context Managers With "contextlib"
In the last two lessons you worked with a class-based context manager.
In this video you’ll learn how to implement a function-based context manager using Python’s contextlib
module.
00:00
Now, I just explained to you how class-based context managers work, but this isn’t the only way to support the with
statement in Python, and this is not the only way to implement a context manager.
00:13
So, there is the contextlib
module in the standard library, and it provides a couple of abstractions on top of the basic context manager protocol.
00:23
And this can make your life a little easier if you’re trying to implement a use case that matches well with what the contextlib
module offers.
00:32
So, here’s a quick example of what you can do with this. I’m going to re-implement the same ManagedFile
functionality using the contextlib
library. So, there’s a decorator in there called contextmanager
and this thing is highly useful.
00:47
What that allows you to do is you can define objects that follow the context manager protocol that you can use with the with
statement simply by writing a generator.
00:59
So, when looking at this code, again, you can see our familiar try
and finally
pattern here, where I’m acquiring the resource and then I’m yielding it, and then later, I’m closing the resource.
01:12
And what happens is that this @contextmanager
decorator will turn this generator function—or, this generator that I just defined here—it will turn that into a full-blown context manager that I can use with the with
statement. So again, I can do something like this.
01:32
I can say with managed_file('hello.txt')
—
01:40
I’m just going to call it f
again. I can say, “Write something to the file,” and of course we can also write more stuff to the same file. And now, when I run this, we’re actually writing to the file.
01:52
If you’re wondering what this is—so, this is just the number of characters written, because .write()
returns how many characters were written to the file, right?
01:59 It’s just kind of leaking back into my interpreter session here.
Dan Bader RP Team on May 9, 2019
I can’t get why a generator is needed.. Could you clarify that please?
Ah, the reason is that contextlib.contextmanager
requires a generator :) Using a generator allows the function to be temporarily “paused” and then later resumed again for the context manager’s “exit” step. A regular function can’t do that sort of thing, hence the yield
to define a generator.
Become a Member to join the conversation.
Gilles Consulting on May 9, 2019
Hello, Thanks for you videos. very clear, even if for this one I have 2 questions:
I am wondering why you defined a generator, with a
yield
, instead of areturn
. well, it does not work with areturn
:) I can’t get why a generator is needed.. Could you clarify that please?Also, if I understand properly, in you managed_file function the “try:” is taken in charge by the
__enter__
function, and the finally by the__exit__
one (cf the class you defined in your previous video to reproduce thewith
behavior. Could you confirm if it’s correct?Thank you in advance.