Python Basics #18 — File Read/Write Vol. 2
Continuing from the previous lesson, this lesson covers writing files. If you haven’t read the previous lesson, please start there first:
Python Basics #17 — File Read/Write Vol. 1
File read/write modes #
| Mode | Description |
|---|---|
| r | Read-only (default — can be omitted). |
| w | Write-only. Creates a new file if one with the same name doesn’t exist; otherwise overwrites. Overwriting deletes existing data — be careful. |
| x | Write-only, but raises an error if a file with the same name exists. Think of it as a safer w. |
| a | Append. Creates a new file if one with the same name doesn’t exist; otherwise appends to the end. |
| t | Text mode (default — can be omitted). |
| b | Binary mode. For non-text files like PDFs and images. |
| r+ | Read and write simultaneously. |
| w+ | Read and write simultaneously. |
Writing files is similar to reading. As with reading, use the open function. For the mode parameter, use one of w, x, or a.
Let’s write a file using w. To write, use the write method on the file object. write takes a string and writes it to the file.
with open(file='out.txt', mode='w', encoding='utf8') as file:
file.write('line one')
file.write('line two')line oneline twoWe meant to write two lines, but they ended up on one. write doesn’t add a newline. Add \n characters explicitly to fix it:
with open(file='out.txt', mode='w', encoding='utf8') as file:
file.write('line one\n')
file.write('line two\n')line one
line twoIf adding newlines every time feels tedious, use print instead. Let’s check print’s help:
help(print)Help on built-in function print in module builtins:
print(...)
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep: string inserted between values, default a space.
end: string appended after the last value, default a newline.
flush: whether to forcibly flush the stream.print defaults end to a newline character and file to sys.stdout. sys.stdout is essentially the command prompt or terminal. If you pass a file object as the file argument, the string is written to the file instead of the console — and you don’t need to add a trailing \n each time.
with open(file='out.txt', mode='w', encoding='utf8') as file:
print('line 1', file=file)
print('line 2', file=file)line 1
line 2Note: each time you re-run the code, the previous file contents are wiped and replaced by new text. With w mode, if out.txt doesn’t exist a new file is created; if it does exist, it gets overwritten — all previous contents are deleted. Be careful not to accidentally lose data.
Now let’s write a list of dictionaries (country information) to a file:
countries = [
{'country': 'South Korea', 'capital': 'Seoul', 'region': 'Asia'},
{'country': 'Japan', 'capital': 'Tokyo', 'region': 'Asia'},
{'country': 'China', 'capital': 'Beijing', 'region': 'Asia'},
]
with open(file='country.txt', mode='w', encoding='utf8') as file:
for country in countries:
line = 'country: {country}, capital: {capital}, region: {region}\n'.format(**country)
file.write(line)country: South Korea, capital: Seoul, region: Asia
country: Japan, capital: Tokyo, region: Asia
country: China, capital: Beijing, region: AsiaSaved correctly. To save a list or dictionary from your program to a text file, you can use the str function:
countries = [
{'country': 'South Korea', 'capital': 'Seoul', 'region': 'Asia'},
{'country': 'Japan', 'capital': 'Tokyo', 'region': 'Asia'},
{'country': 'China', 'capital': 'Beijing', 'region': 'Asia'},
]
with open(file='country.txt', mode='w', encoding='utf8') as file:
file.write(str(countries))[{'country': 'South Korea', 'capital': 'Seoul', 'region': 'Asia'}, {'country': 'Japan', 'capital': 'Tokyo', 'region': 'Asia'}, {'country': 'China', 'capital': 'Beijing', 'region': 'Asia'}]The list object was saved in code form. But when you read this back, the Python interpreter doesn’t recognize it as a list — it returns a string. Confirm:
countries = [
{'country': 'South Korea', 'capital': 'Seoul', 'region': 'Asia'},
{'country': 'Japan', 'capital': 'Tokyo', 'region': 'Asia'},
{'country': 'China', 'capital': 'Beijing', 'region': 'Asia'},
]
with open(file='country.txt', mode='r', encoding='utf8') as file:
result = file.read()
print(type(result))<class 'str'>To re-use saved data in your program, convert it back to a list or dictionary using the eval function:
countries = [
{'country': 'South Korea', 'capital': 'Seoul', 'region': 'Asia'},
{'country': 'Japan', 'capital': 'Tokyo', 'region': 'Asia'},
{'country': 'China', 'capital': 'Beijing', 'region': 'Asia'},
]
with open(file='country.txt', mode='r', encoding='utf8') as file:
result = file.read()
result = eval(result)
print(type(result))<class 'list'>Now that it’s a list object, you can use it just like the original:
countries = [
{'country': 'South Korea', 'capital': 'Seoul', 'region': 'Asia'},
{'country': 'Japan', 'capital': 'Tokyo', 'region': 'Asia'},
{'country': 'China', 'capital': 'Beijing', 'region': 'Asia'},
]
with open(file='country.txt', mode='r', encoding='utf8') as file:
result = file.read()
result = eval(result)
for country in result:
print(country){'country': 'South Korea', 'capital': 'Seoul', 'region': 'Asia'}
{'country': 'Japan', 'capital': 'Tokyo', 'region': 'Asia'}
{'country': 'China', 'capital': 'Beijing', 'region': 'Asia'}Now the x option. As mentioned, x is a safer version of w: if a file with the same name exists, it raises an error — preventing accidental data loss.
with open(file='country.txt', mode='x', encoding='utf8') as file:
file.write('new data')---------------------------------------------------------------------------
FileExistsError Traceback (most recent call last)
<ipython-input-9-e897f33b1472> in <module>
----> 1 with open(file='country.txt', mode='x', encoding='utf8') as file:
2 file.write('new data')
FileExistsError: [Errno 17] File exists: 'country.txt'FileExistsError was raised and the program terminated.
Now the a option. a is append mode. If a file with the same name doesn’t exist, it creates one. If it does exist, instead of overwriting (like w), it places the cursor at the end of the file and continues writing from there.
existing dataAppend text to append.txt using a:
with open(file='append.txt', mode='a', encoding='utf8') as file:
file.write('appended text')existing dataappended textThe new text was written on the same line as the existing data. When appending, check whether the existing text ends with a newline; if not, prepend a newline to your new text:
with open(file='append.txt', mode='a', encoding='utf8') as file:
file.write('\nappended text')existing data
appended textThat wraps up plain text reading and writing. Special formats like CSV, JSON, YAML, and EXCEL will be covered in separate lessons.
The next post covers errors and exception handling.