@@ -326,8 +326,38 @@ out
326326print(out)
327327```
328328329-We can also use a `with` statement (also known as a [context manager](https://realpython.com/python-with-statement/#the-with-statement-approach)) which enables you to group operations on the file within a block which improves the clarity of your code.
329+We can also use a `with` statement to ensure the files are properly acquired
330+and released.
330331332+Containing the operations within the same block also improves the clarity of your code.
333+334+```{note}
335+This kind of block is formally referred to as a [*context*](https://realpython.com/python-with-statement/#the-with-statement-approach).
336+```
337+338+Let's try to convert the two examples above into a `with` statement.
339+340+We change the writing example first
341+```{code-cell} python3
342+343+with open('newfile.txt', 'w') as f:
344+ f.write('Testing\n')
345+ f.write('Testing again')
346+```
347+348+Note that we do not need to call the `close()` method since the `with` block
349+will ensure the stream is closed at the end of the block.
350+351+With slight modifications, we can also read files using `with`
352+353+```{code-cell} python3
354+with open('newfile.txt', 'r') as fo:
355+ out = fo.read()
356+ print(out)
357+```
358+Now suppose that we want to read input from one file and write output to another.
359+Here's how we could accomplish this task while correctly acquiring and returning
360+resources to the operating system using `with` statements:
331361332362```{code-cell} python3
333363with open("newfile.txt", "r") as f:
@@ -337,30 +367,48 @@ with open("newfile.txt", "r") as f:
337367 fo.write(f'Line {i}: {line} \n')
338368```
339369370+The output file will be
371+340372```{code-cell} python3
341-fo = open('output.txt', 'r')
342-out = fo.read()
343-print(out)
373+with open('output.txt', 'r') as fo:
374+ print(fo.read())
344375```
345376346-We can write the example above under the same context to reduce redundancy
377+We can simplify the example above by grouping the two `with` statements into one line
347378348379```{code-cell} python3
349380with open("newfile.txt", "r") as f, open("output2.txt", "w") as fo:
350381 for i, line in enumerate(f):
351382 fo.write(f'Line {i}: {line} \n')
352383```
353384385+The output file will be the same
386+354387```{code-cell} python3
355-fo = open('output2.txt', 'r')
356-out = fo.read()
357-print(out)
388+with open('output2.txt', 'r') as fo:
389+ print(fo.read())
358390```
359391360-```{note}
361-Note that we only used `r` and `w` mode. There are [more modes](https://www.geeksforgeeks.org/reading-writing-text-files-python/) you could experiment with.
392+Suppose we want to continue to write into the existing file
393+instead of overwriting it.
394+395+we can switch the mode to `a` which stands for append mode
396+397+```{code-cell} python3
398+with open('output2.txt', 'a') as fo:
399+ fo.write('\nThis is the end of the file')
400+```
401+402+```{code-cell} python3
403+with open('output2.txt', 'r') as fo:
404+ print(fo.read())
362405```
363406407+```{note}
408+Note that we only covered `r`, `w`, and `a` mode here, which are the most commonly used modes.
409+Python provides [a variety of modes](https://www.geeksforgeeks.org/reading-writing-text-files-python/)
410+that you could experiment with.
411+```
364412365413### Paths
366414