Python File Handling: Read and Write Files
SkillVeris Team
Engineering Team

Python reads and writes files with the built-in open() function, which returns a file object you can read from or write to.
In this guide, you'll learn:
- Always use the with statement — it opens the file and closes it automatically, even if an error occurs.
- The mode argument controls behavior: 'r' to read, 'w' to overwrite, 'a' to append, and 'b' for binary data.
- Read a whole file with .read(), a single line with .readline(), or loop over the file object line by line for large files.
- Writing uses .write() or .writelines(); remember that 'w' truncates the file while 'a' preserves existing content.
1How File Handling Works in Python
Python handles files through the built-in open() function, which takes a file path and a mode and returns a file object. You then read from or write to that object and close it when done. The open-work-close cycle is the foundation of all file input and output.
The recommended way to manage that cycle is the with statement, which opens the file for the duration of an indented block and closes it automatically at the end — even if your code raises an exception. This prevents the common bug of leaving files open.
- with open('notes.txt', 'r', encoding='utf-8') as f:
- content = f.read()
- print(content) # file is already closed here
2File Modes Explained
The second argument to open() is the mode, a short string that tells Python what you intend to do with the file. Choosing the wrong mode is a frequent source of bugs — especially 'w', which erases existing content.
- 'r' — read (default); errors if the file does not exist.
- 'w' — write; creates the file or truncates an existing one to empty.
- 'a' — append; adds to the end, creating the file if needed.
- 'x' — exclusive create; fails if the file already exists.
- 'b' — binary mode, combined with others like 'rb' or 'wb'.
- 'r+' — read and write without truncating.
⚠️Watch Out
Opening a file in 'w' mode immediately erases its contents, even before you write anything. If you want to add to a file, use 'a' to append instead.
3Reading Files
Python offers several ways to read, each suited to a different need. Use .read() for the whole file as one string, .readline() for one line at a time, and .readlines() for a list of all lines. For large files, looping directly over the file object is the most memory-efficient choice.
- with open('log.txt', encoding='utf-8') as f:
- whole = f.read() # entire file as one string
- with open('log.txt', encoding='utf-8') as f:
- for line in f: # memory-friendly, one line at a time
- print(line.rstrip()) # strip the trailing newline
Why Loop Over the File
Reading a huge file with .read() loads everything into memory at once. Iterating line by line reads only one line at a time, so it scales to files far larger than available RAM.
4Writing and Appending Files
To write, open the file in 'w' or 'a' mode and call .write() with a string, or .writelines() with a list of strings. Note that .write() does not add newlines for you — include \n yourself where you want line breaks.
- with open('out.txt', 'w', encoding='utf-8') as f:
- f.write('First line\n')
- f.writelines(['a\n', 'b\n', 'c\n'])
- with open('out.txt', 'a', encoding='utf-8') as f:
- f.write('Appended line\n') # kept previous content
💡Pro Tip
print() can write to a file too: print('hello', file=f) adds the newline automatically, which is often more convenient than f.write().
5Modern Paths With pathlib
The pathlib module provides an object-oriented way to work with file paths that reads cleanly and works the same on Windows, macOS, and Linux. Its Path objects offer shortcut methods for common read and write tasks.
- from pathlib import Path
- p = Path('data') / 'notes.txt' # cross-platform join
- text = p.read_text(encoding='utf-8') # read in one call
- p.write_text('new content', encoding='utf-8') # write in one call
- print(p.exists(), p.suffix) # True .txt
6Binary Files and Encoding
Text mode decodes bytes into strings using an encoding; binary mode gives you the raw bytes untouched. Use binary mode for images, audio, and any non-text data, and always specify encoding='utf-8' for text to avoid platform-dependent defaults.
- with open('photo.jpg', 'rb') as f:
- data = f.read() # bytes, not text
- with open('copy.jpg', 'wb') as f:
- f.write(data)
- # For text, be explicit about encoding to stay portable
- open('notes.txt', encoding='utf-8')
7Common Mistakes to Avoid
File handling bugs are usually simple to fix once you know the pattern.
- Forgetting to close files — always use with so closing is automatic.
- Using 'w' when you meant 'a', wiping out existing data.
- Expecting .write() to add newlines — it does not; include \n yourself.
- Ignoring encoding, which causes garbled text across platforms — pass encoding='utf-8'.
- Reading a giant file with .read() and exhausting memory — loop over the file instead.
- Not handling FileNotFoundError when a file may be missing.
8Key Takeaways
Reliable file handling in Python follows a small set of habits.
- Use open() with the with statement so files close automatically.
- Pick the mode carefully: 'r' reads, 'w' overwrites, 'a' appends.
- Loop over the file object to read large files efficiently.
- Always pass encoding='utf-8' for text files.
- Consider pathlib for clean, cross-platform path handling.
9Frequently Asked Questions
Q: Why should I use the with statement to open files? A: The with statement automatically closes the file when the block ends, even if an error is raised inside it. This prevents resource leaks and the corrupted or locked files that come from forgetting to call .close().
Q: What is the difference between 'w' and 'a' mode? A: 'w' opens a file for writing and immediately truncates it to empty, discarding any existing content. 'a' opens for appending and adds new data to the end, preserving what was already there. Use 'a' when you want to keep old content.
Q: How do I read a large file without running out of memory? A: Loop directly over the file object: for line in f. This reads one line at a time instead of loading the whole file into memory with .read(), so it works for files larger than your available RAM.
Q: How do I avoid garbled characters when reading text? A: Always pass encoding='utf-8' to open(). Without it, Python uses a platform-dependent default that can misread non-ASCII characters, producing garbled text or a UnicodeDecodeError.
Related Reading
Get The Print Version
Download a PDF of this article for offline reading.
About the Publisher
SkillVeris Team
Engineering Team
Our engineering writers turn abstract code concepts into hands-on, project-driven learning experiences.
View all postsRelated Posts
Never miss an update
Get the latest tutorials and guides delivered to your inbox.
No spam. Unsubscribe anytime.