Introduction to Context Managers
00:00 In the previous lesson, I gave an overview of the course. In this lesson, I’ll be showing you the how and why of context managers.
00:08 This is the problem. Consider the three lines of code that you need to open and write to a file. If this line fails, resulting in an exception, then this line won’t run.
00:20 If the exception results in your script exiting, the operating system will typically close the file for you. But what if you catch the error somewhere else to inform the user? Well, you’ve still got an open file handle.
00:32 Your operating system has a maximum number of file handles that it will allow you to open at any given time. It typically isn’t a small number. On many Linux boxes, it defaults to just over a thousand, but if you’re executing a long-running program, lack of resource management can catch up with you.
Dad joke in the title aside, a common way of dealing with the problem is to use a
finally block. The
finally portion of the block runs whether or not there was an exception, guaranteeing that your file gets closed.
01:04 The one drawback of this approach is you have to remember to do it each and every time you deal with a resource. Spoiler alert, context managers don’t have this challenge.
open() function can be used as both a function and as a context manager. To use it as a context manager, you write the
When you instantiate
open() as a context manager, it returns a file handle. That’s seen here, after the
with statements form a code block.
Everything indented underneath it is in the block. When the block is finished, the context manager automatically closes the file for you. This is in contrast to the
finally case. Here, you don’t have to remember to handle the resource.
It’s done by the context manager. Not having to remember is good. The downside is you don’t have an opportunity to deal with the exception. It gets caught, and the file gets closed, but you can’t inform the user like you would with the
except portion of the
Context managers are built following a protocol. They are objects, like everything in Python, and these objects need to have a
.__enter__() method, which, if it returns something, becomes the target of the
as portion of the statement, and a
.__exit__() method that is called when the context block goes out of scope.
This is where your resource closing goes. When Python hits a
with statement, it calls the context manager’s
.__enter__() method, provides the result of
.__enter__() to the
as target, runs the code block underneath the
with, and finally, once the block exits, it calls the context manager’s
02:49 This method actually takes arguments that give information about whether there was an exception, but I’ll get back to that later.
Python 3.1—yep, that’s just a single 1; this is quite some time ago—introduced the capability of instantiating multiple context managers in the same
03:08 This example opens a file for reading and opens a different file for writing. This is a common pattern when you’re doing data transformation. A little more on this in a future lesson.
03:21 Next up, I’ll give you a tour of some context managers from the standard library and how they’re used.
Become a Member to join the conversation.