Skip to content

Commit 3d6b065

Browse files
authored
Merge pull request #253 from QuantEcon/add-with
[pthon_essentials] Adding context managers (with statements)
2 parents daa74fc + 872c33e commit 3d6b065

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed

lectures/python_essentials.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,89 @@ out
326326
print(out)
327327
```
328328

329+
In fact, the recommended approach in modern Python is to use a `with` statement to ensure the files are properly acquired and released.
330+
331+
Containing the operations within the same block also improves the clarity of your code.
332+
333+
```{note}
334+
This kind of block is formally referred to as a [*context*](https://realpython.com/python-with-statement/#the-with-statement-approach).
335+
```
336+
337+
Let's try to convert the two examples above into a `with` statement.
338+
339+
We change the writing example first
340+
```{code-cell} python3
341+
342+
with open('newfile.txt', 'w') as f:
343+
f.write('Testing\n')
344+
f.write('Testing again')
345+
```
346+
347+
Note that we do not need to call the `close()` method since the `with` block
348+
will ensure the stream is closed at the end of the block.
349+
350+
With slight modifications, we can also read files using `with`
351+
352+
```{code-cell} python3
353+
with open('newfile.txt', 'r') as fo:
354+
out = fo.read()
355+
print(out)
356+
```
357+
Now suppose that we want to read input from one file and write output to another.
358+
Here's how we could accomplish this task while correctly acquiring and returning
359+
resources to the operating system using `with` statements:
360+
361+
```{code-cell} python3
362+
with open("newfile.txt", "r") as f:
363+
file = f.readlines()
364+
with open("output.txt", "w") as fo:
365+
for i, line in enumerate(file):
366+
fo.write(f'Line {i}: {line} \n')
367+
```
368+
369+
The output file will be
370+
371+
```{code-cell} python3
372+
with open('output.txt', 'r') as fo:
373+
print(fo.read())
374+
```
375+
376+
We can simplify the example above by grouping the two `with` statements into one line
377+
378+
```{code-cell} python3
379+
with open("newfile.txt", "r") as f, open("output2.txt", "w") as fo:
380+
for i, line in enumerate(f):
381+
fo.write(f'Line {i}: {line} \n')
382+
```
383+
384+
The output file will be the same
385+
386+
```{code-cell} python3
387+
with open('output2.txt', 'r') as fo:
388+
print(fo.read())
389+
```
390+
391+
Suppose we want to continue to write into the existing file
392+
instead of overwriting it.
393+
394+
we can switch the mode to `a` which stands for append mode
395+
396+
```{code-cell} python3
397+
with open('output2.txt', 'a') as fo:
398+
fo.write('\nThis is the end of the file')
399+
```
400+
401+
```{code-cell} python3
402+
with open('output2.txt', 'r') as fo:
403+
print(fo.read())
404+
```
405+
406+
```{note}
407+
Note that we only covered `r`, `w`, and `a` mode here, which are the most commonly used modes.
408+
Python provides [a variety of modes](https://www.geeksforgeeks.org/reading-writing-text-files-python/)
409+
that you could experiment with.
410+
```
411+
329412
### Paths
330413

331414
```{index} single: Python; Paths

0 commit comments

Comments
 (0)