So far, we’ve only been using context managers within the context (Ha! Get it?) of one file. In most programs, there might be a need to use context managers for a couple of different scenarios that include working with multiple files! For example, we might want to:
- Work with information from multiple files.
- Copy the same information to multiple files.
- Copy information from one file to another.
To accomplish this goal of working with multiple resources at once, context managers can be nested together in a with
statement to manage multiple resources simultaneously.
Let’s imagine we have two files: a teacher.txt
file and a student.txt
. We want to copy all the information on the student file to the teachers. Our code might look like this:
with open('teacher.txt', 'w') as teacher, open('student.txt', 'r') as student: teacher.write(student.read())
Notice:
- The
with
statement is being called once but invoking two context managers. This is a single-line nestedwith
statement. - Each context manager is separated by a comma and has its own target variable.
- Our
teacher.txt
file is being opened in write mode because it will be written into and ourstudent.txt
is opened in read mode because we are attempting to copy the text into the teacher’s file - The resulting
teacher.txt
file will now include everything that was in thestudent.txt
file. - Here we have chosen to use the
open()
built-in function rather than a custom context manager. It is entirely possible to use our own in place of theopen()
function.
We can also write the above nested
context managers in a slightly different way:
with open("teacher.txt", "w") as teacher: with open("student.txt", "r") as student: teacher.write(student.read())
Notice that this syntax is almost similar to the first method. However, here are some differences to note:
- The
with
statement is being called twice - The
with
statement statement to openstudent.txt
in read mode is nested in the code block of thewith
statement that opensteacher.txt
in write mode. - This method, though slightly longer gives a clearer visual of
nesting
and is preferable when working with more than two context managers.
Let’s practice nesting context manager with our poem_files
decorator-based context manager from earlier!
Instructions
Let’s return to our poem context manager. This time, we want to start transferring poems from a poem.txt
file to a card.txt
file. We plan to create some poem greeting cards for all our friends!
Write a nested context manager that uses the poem_files
context manager to open poem.txt
in read mode and saves it to a variable called poem
Nested inside, use the card_files
context manager to open the card.txt
file in write mode and saves it to a variable called card
.
Print poem
and card
to confirm we can access both files.
Finally, inside of our nested context managers, and under our print statements, write to card.txt
the contents of poem.txt
.