Redirecting Stdout and a File Writer
00:00 In the previous lesson, I got you started writing a custom, class-based context manager. In this lesson, I’ll show you a real usage of a context manager and then show you how to write one using the function style.
00:13 I’ll be going over two examples. In the first, I’ll show you how to redirect standard out inside of a block, and in the second, I’ll write a context manager for writing files, but this time with the function-style implementation.
00:29 Okay, let’s do something a little more useful than just saying hello. This code redirects standard out within the context block. The initializer takes a file handle where standard out will be redirected to.
00:42
.__enter__()
saves the system standard out into a variable so that you can restore it later, then changes where standard out points to—in this case, the file handle from the initializer.
00:55
This .__enter__()
does not return anything, so if you use the as
clause, your value will be None
. .__exit__()
then returns standard out to its original value.
01:07
Notice that I use *args
to be lazy and avoid typing exc_type
, exc_value
, exc_tb
. And because I’m not doing anything with the exception case here, I can just ignore it all. Let’s go try this code out.
01:37
Here I’m using the open()
context manager to open a file. This is the file that I’m going to be redirecting my content to.
01:49 And this nested contact manager is my actual redirector. It takes a reference to the file and will be redirecting standout out into that file.
02:04 Printing something inside of the block … printing something outside of the block … and there’s the result. Only the second print gets output to the REPL because the first one got trapped by my redirected context manager. Let me show you the file.
02:31 And there you go. What I printed got sent the file instead. And because all of this was taken care of by the context manager, I don’t have to remember to reset standard out when I’m done playing around with it.
02:47
You can write a context manager using a function and the @contextmanager
decorator instead of a class if you like. This function is a specialization of file open, explicitly for writing files. First off, you need the decorator from the contextlib
module.
03:04
Then you decorate your function. And then inside of the function, everything revolves around the yield
keyword. Everything before yield
is the equivalent of what happens in .__enter__()
.
03:16
Everything after the yield
is the equivalent of what happens in .__exit__()
. You can yield a value, like I have here, and that is what is used as the as
part of your statement, your target. And that’s it.
03:32 Context manager as a function instead of a class. It’s that simple. Let’s go try it out.
03:41
Importing … creating the context manager using "output.txt
as my output file, and the target is named file
…
03:57
writing something to the file. And there you go. That 10
is because file.write()
returns the number of bytes written. Since it’s the last line in the block, and I’m in the REPL, the REPL is showing me the value. In a script, you’d typically just ignore this result. Let’s look at the file … once again using pathlib
…
04:23 and there’s the content. My function-based context manager is a file-writing machine. You’ve seen all sorts of context managers—some from the standard library, and you’ve even written a few of your own.
04:37 In the last lesson, I’ll summarize the course and quickly show you a new context manager that got added in Python 3.11.
Become a Member to join the conversation.