Input and output — I/O — means everything your program reads in or writes out. Most of the time that is files, and Python keeps it short:
with open("notes.txt", "w", encoding="utf-8") as f:
f.write("First line\n")
with open("notes.txt", encoding="utf-8") as f:
print(f.read())The with block closes the file for you even if something fails inside it. Use it every time and files stop being something you have to clean up.
Reading#
# The whole file as one string
with open("notes.txt", encoding="utf-8") as f:
text = f.read()
# Every line as a list
with open("notes.txt", encoding="utf-8") as f:
lines = f.readlines()
# One line at a time — works on files too big to fit in memory
with open("notes.txt", encoding="utf-8") as f:
for line in f:
print(line.strip())The third form is the one to reach for by default. .strip() is there because each line still carries its newline character — forget it and comparisons like line == "quit" mysteriously fail.
Writing and appending#
with open("log.txt", "w", encoding="utf-8") as f: # empties the file first
f.write("Starting\n")
with open("log.txt", "a", encoding="utf-8") as f: # adds to the end
f.write("Another line\n")Two things surprise people. write() does not add a newline the way print() does, so you add \n yourself. And "w" does not append — it empties the file the moment it opens, before you write anything.
The modes#
| Mode | Does | If the file is missing |
|---|---|---|
"r" |
Read (the default) | FileNotFoundError |
"w" |
Write, emptying it first | Creates it |
"a" |
Append to the end | Creates it |
"x" |
Write only if new | Creates it; errors if it exists |
"x" is worth knowing when overwriting would be a bug — it makes Python refuse rather than silently destroy.
Handling a file that is not there#
try:
with open("settings.txt", encoding="utf-8") as f:
settings = f.read()
except FileNotFoundError:
settings = "" # first run — perfectly normalCatch the specific error rather than everything. See Python try/except explained.
Paths that work everywhere#
A bare filename is relative to the folder your terminal is in, not where the script lives. Run the script from elsewhere and it reads and writes somewhere else entirely.
from pathlib import Path
HERE = Path(__file__).parent
notes = HERE / "notes.txt" # always next to the script
print(notes.exists())
print(notes.suffix) # .txt
print(notes.stem) # notes
notes.parent.mkdir(parents=True, exist_ok=True)pathlib joins paths correctly on Windows, macOS and Linux, so you never hand-write a slash and break it on someone else’s machine.
Encoding#
Python picks a default text encoding from your system, and on some Windows setups that is not UTF-8. Your file works for you and raises UnicodeDecodeError for someone else, or quietly mangles every accented character.
with open("notes.txt", "w", encoding="utf-8") as f:
f.write("café ☕")Write encoding="utf-8" on every text file you open. It costs nothing and removes an entire class of bug.
Structured data#
The moment you want to store more than lines of text, use JSON rather than inventing a separator:
import json
tasks = [{"text": "Learn I/O", "done": False}]
with open("tasks.json", "w", encoding="utf-8") as f:
json.dump(tasks, f, indent=2)
try:
with open("tasks.json", encoding="utf-8") as f:
loaded = json.load(f)
except (FileNotFoundError, json.JSONDecodeError):
loaded = []Questions people ask#
Do I have to close the file?
Not if you use with — it closes automatically, including when an exception is raised. Without it you must call f.close() yourself.
How do I edit one line in the middle?
Read the file into a list, change the item, write the whole thing back. Text files have no concept of inserting in the middle.
What about very large files?
Loop over the file object one line at a time and never call read() or readlines(). Memory use then stays flat however big the file is.
How do I delete or rename a file?
Path("old.txt").rename("new.txt") and Path("junk.txt").unlink(). Check .exists() first or catch FileNotFoundError.
Where to go next#
- Reading and writing files in Python — the same ground with more worked examples
- Python try/except explained
- Build a to-do list that saves its data