Python File Handling: Read, Write, and Manage Files
File handling is the process of working with files stored on a computer. Python provides simple and powerful tools for creating, reading, writing, updating, and managing files.
File handling is useful whenever a program needs to store data permanently instead of keeping it only in memory.
For example, a program can save:
- User information
- Notes
- Student records
- Application logs
- Configuration data
- CSV datasets
- JSON data
- Reports
- Backup files
Common file types include:
| Extension | Purpose |
|---|---|
.txt | Plain text |
.csv | Tabular data |
.json | Structured data |
.log | Application logs |
.py | Python source code |
Why Use File Handling?
Consider this program:
1name = input("Enter your name: ") 2 3print("Hello,", name)
The value is stored only while the program is running.
After the program exits, the information is lost.
A file can store the information permanently:
1name = input("Enter your name: ") 2 3with open("users.txt", "a", encoding="utf-8") as file: 4 file.write(name + "\n") 5 6print("User saved successfully.")
Now the name remains in users.txt even after the program finishes.
This makes file handling an important part of building real-world Python applications.
What Is a File?
A file is a named collection of data stored on a storage device.
For example:
1notes.txt
might contain:
1Python is easy to learn. 2Python is powerful. 3Python is widely used.
Python can read this information, modify it, or create new files.
Python File Handling Workflow
A typical file-handling operation follows this process:
1Open File 2 ↓ 3Read / Write / Append 4 ↓ 5Process Data 6 ↓ 7Close File
The recommended Python approach is to use the with statement:
1with open("notes.txt", "r", encoding="utf-8") as file: 2 content = file.read()
The with statement automatically closes the file when the block finishes, even if an exception occurs.
Opening a File
Python provides the built-in open() function for opening files.
Syntax:
1open(file, mode)
Example:
1file = open("notes.txt", "r", encoding="utf-8")
The arguments are:
file→ File name or pathmode→ How the file should be openedencoding→ Character encoding used for text
For text files, explicitly specifying UTF-8 is a good practice:
1with open("notes.txt", "r", encoding="utf-8") as file: 2 print(file.read())
File Modes in Python
Python provides several file modes.
| Mode | Meaning |
|---|---|
r | Read |
w | Write and overwrite |
a | Append |
x | Create a new file |
r+ | Read and write |
w+ | Write and read, overwriting existing content |
a+ | Append and read |
rb | Read binary |
wb | Write binary |
The most commonly used modes are:
1r → read 2w → write 3a → append 4x → create
Reading a File
Suppose notes.txt contains:
1Python is easy. 2Python is powerful.
You can read the entire file with read():
1with open("notes.txt", "r", encoding="utf-8") as file: 2 content = file.read() 3 4print(content)
Output:
1Python is easy. 2Python is powerful.
The with block automatically closes the file.
Reading a Specific Number of Characters
The read() method can accept a number indicating how many characters to read.
1with open("notes.txt", "r", encoding="utf-8") as file: 2 content = file.read(10) 3 4print(content)
For example, the output might be:
1Python is
The exact result depends on the contents of the file.
Reading One Line
Use readline() to read one line at a time.
1with open("notes.txt", "r", encoding="utf-8") as file: 2 first_line = file.readline() 3 4print(first_line)
If the file contains:
1Python is easy. 2Python is powerful.
the result is approximately:
1Python is easy.
The returned line may contain a trailing newline character (\n).
Reading All Lines
The readlines() method returns the lines as a list.
1with open("notes.txt", "r", encoding="utf-8") as file: 2 lines = file.readlines() 3 4print(lines)
Output:
1['Python is easy.\n', 'Python is powerful.\n']
For large files, however, reading every line into a list may consume unnecessary memory.
A better approach is often to iterate over the file:
1with open("notes.txt", "r", encoding="utf-8") as file: 2 for line in file: 3 print(line.strip())
This processes the file one line at a time.
Writing to a File
The w mode writes data to a file.
1with open("notes.txt", "w", encoding="utf-8") as file: 2 file.write("Welcome to Python!")
The file will contain:
1Welcome to Python!
Be careful with w mode.
If the file already contains data, opening it with "w" normally truncates the existing content.
For example:
1with open("notes.txt", "w", encoding="utf-8") as file: 2 file.write("New content")
Previous contents are replaced.
Writing Multiple Lines
You can write multiple lines using \n:
1students = [ 2 "Ankit", 3 "Rahul", 4 "Aman", 5] 6 7with open("students.txt", "w", encoding="utf-8") as file: 8 for student in students: 9 file.write(student + "\n")
The file becomes:
1Ankit 2Rahul 3Aman
For larger collections of text, writelines() can also be useful:
1students = [ 2 "Ankit\n", 3 "Rahul\n", 4 "Aman\n", 5] 6 7with open("students.txt", "w", encoding="utf-8") as file: 8 file.writelines(students)
Appending to a File
The a mode adds new data to the end of an existing file.
1with open("notes.txt", "a", encoding="utf-8") as file: 2 file.write("\nLearning Python File Handling.")
Existing content is preserved.
For example:
1Welcome to Python! 2 3Learning Python File Handling.
Append mode is useful for:
- Notes applications
- Logs
- Activity records
- History files
- Incrementally stored data
Creating a New File with x
The x mode creates a new file.
1with open("new_file.txt", "x", encoding="utf-8") as file: 2 file.write("This is a new file.")
If the file already exists, Python raises:
1FileExistsError
You can handle this with exception handling:
1try: 2 with open("new_file.txt", "x", encoding="utf-8") as file: 3 file.write("New file created.") 4except FileExistsError: 5 print("The file already exists.")
Closing a File
When using open() directly, you should close the file:
1file = open("notes.txt", "r", encoding="utf-8") 2 3try: 4 print(file.read()) 5finally: 6 file.close()
However, the preferred approach is:
1with open("notes.txt", "r", encoding="utf-8") as file: 2 print(file.read())
The with statement handles cleanup automatically.
Why Use the with Statement?
The with statement is recommended because it ensures that the file is properly closed.
Instead of:
1file = open("notes.txt", "r", encoding="utf-8") 2 3content = file.read() 4 5file.close()
use:
1with open("notes.txt", "r", encoding="utf-8") as file: 2 content = file.read()
This is cleaner, safer, and easier to maintain.
Using pathlib for File Paths
Python's pathlib module provides a modern way to work with file and directory paths.
1from pathlib import Path 2 3file_path = Path("notes.txt") 4 5with file_path.open("r", encoding="utf-8") as file: 6 print(file.read())
You can also use convenient methods for simple text files.
Write Text
1from pathlib import Path 2 3Path("notes.txt").write_text( 4 "Python File Handling", 5 encoding="utf-8", 6)
Read Text
1from pathlib import Path 2 3content = Path("notes.txt").read_text(encoding="utf-8") 4 5print(content)
Check Whether a File Exists
1from pathlib import Path 2 3file_path = Path("notes.txt") 4 5if file_path.exists(): 6 print("File exists.") 7else: 8 print("File does not exist.")
For modern Python applications, pathlib is often preferable to manually constructing filesystem paths with strings.
Checking Whether a File Exists
You can use pathlib:
1from pathlib import Path 2 3file_path = Path("data.txt") 4 5if file_path.is_file(): 6 print("File exists.") 7else: 8 print("File not found.")
You can also use os.path.exists():
1import os 2 3if os.path.exists("data.txt"): 4 print("File exists.") 5else: 6 print("File not found.")
For new code, pathlib is often the cleaner option.
Handling Missing Files
If you try to read a file that doesn't exist:
1with open("data.txt", "r", encoding="utf-8") as file: 2 print(file.read())
Python raises:
1FileNotFoundError
You can handle the error:
1try: 2 with open("data.txt", "r", encoding="utf-8") as file: 3 content = file.read() 4 5 print(content) 6 7except FileNotFoundError: 8 print("The file does not exist.")
This prevents the program from crashing unexpectedly.
Reading a File Safely
A reusable function can make file handling easier:
1from pathlib import Path 2 3 4def read_text_file(filename): 5 path = Path(filename) 6 7 if not path.is_file(): 8 return None 9 10 return path.read_text(encoding="utf-8") 11 12 13content = read_text_file("notes.txt") 14 15if content is None: 16 print("File not found.") 17else: 18 print(content)
Functions like this are useful when the same operation is needed in multiple parts of an application.
Working With CSV Files
CSV stands for Comma-Separated Values.
CSV files are commonly used for tabular data.
Example:
1students.csv
1Name,Marks 2Ankit,95 3Rahul,88 4Aman,91
Python provides the built-in csv module for working with CSV files.
Writing CSV Data
1import csv 2 3students = [ 4 ["Name", "Marks"], 5 ["Ankit", 95], 6 ["Rahul", 88], 7 ["Aman", 91], 8] 9 10with open("students.csv", "w", newline="", encoding="utf-8") as file: 11 writer = csv.writer(file) 12 writer.writerows(students)
The generated file contains:
1Name,Marks 2Ankit,95 3Rahul,88 4Aman,91
Using csv.writer() is preferable to manually joining values with commas because CSV data can contain quoting and escaping rules.
Reading CSV Data
1import csv 2 3with open("students.csv", "r", newline="", encoding="utf-8") as file: 4 reader = csv.reader(file) 5 6 for row in reader: 7 print(row)
Output:
1['Name', 'Marks'] 2['Ankit', '95'] 3['Rahul', '88'] 4['Aman', '91']
Notice that values read by csv.reader() are strings.
If you need marks as numbers, convert them:
1import csv 2 3with open("students.csv", "r", newline="", encoding="utf-8") as file: 4 reader = csv.DictReader(file) 5 6 for row in reader: 7 name = row["Name"] 8 marks = int(row["Marks"]) 9 10 print(name, marks)
Using csv.DictWriter
When CSV columns have meaningful names, DictWriter can make the code easier to understand.
1import csv 2 3students = [ 4 {"name": "Ankit", "marks": 95}, 5 {"name": "Rahul", "marks": 88}, 6 {"name": "Aman", "marks": 91}, 7] 8 9with open("students.csv", "w", newline="", encoding="utf-8") as file: 10 fieldnames = ["name", "marks"] 11 12 writer = csv.DictWriter(file, fieldnames=fieldnames) 13 14 writer.writeheader() 15 writer.writerows(students)
Working With JSON Files
JSON stands for JavaScript Object Notation.
JSON is widely used for storing and exchanging structured data.
Example:
1{ 2 "name": "Ankit", 3 "age": 22, 4 "city": "Delhi" 5}
Python provides the built-in json module for reading and writing JSON.
Writing JSON
1import json 2 3student = { 4 "name": "Ankit", 5 "age": 22, 6 "city": "Delhi", 7 "skills": ["Python", "Docker", "Git"], 8} 9 10with open("student.json", "w", encoding="utf-8") as file: 11 json.dump(student, file, indent=4)
The generated file will look like:
1{ 2 "name": "Ankit", 3 "age": 22, 4 "city": "Delhi", 5 "skills": [ 6 "Python", 7 "Docker", 8 "Git" 9 ] 10}
The indent=4 argument makes the JSON easier for humans to read.
Reading JSON
Use json.load() to read JSON from a file.
1import json 2 3with open("student.json", "r", encoding="utf-8") as file: 4 student = json.load(file) 5 6print(student["name"]) 7print(student["skills"])
Output:
1Ankit 2['Python', 'Docker', 'Git']
JSON and Python Data Types
Python automatically converts common JSON-compatible values.
| Python | JSON |
|---|---|
dict | Object |
list | Array |
str | String |
int / float | Number |
True / False | true / false |
None | null |
For example:
1data = { 2 "name": "Ankit", 3 "active": True, 4 "score": None, 5}
can be serialized to JSON.
Binary Files
Not all files contain human-readable text.
Images, PDFs, audio files, and many other formats are binary data.
Binary files should be opened with modes such as:
1rb → read binary 2wb → write binary
Example:
1with open("image.jpg", "rb") as file: 2 data = file.read() 3 4print("Bytes:", len(data))
When copying binary data:
1with open("image.jpg", "rb") as source: 2 data = source.read() 3 4with open("image_copy.jpg", "wb") as destination: 5 destination.write(data)
For large files, processing data in chunks can reduce memory usage.
Practice Project 1: Notes Application
Let's create a simple command-line notes application.
The application will allow users to:
- Add a note
- View notes
- Exit
1from pathlib import Path 2 3NOTES_FILE = Path("notes.txt") 4 5 6def add_note(): 7 note = input("Enter your note: ").strip() 8 9 if not note: 10 print("Note cannot be empty.") 11 return 12 13 with NOTES_FILE.open("a", encoding="utf-8") as file: 14 file.write(note + "\n") 15 16 print("Note saved successfully.") 17 18 19def view_notes(): 20 if not NOTES_FILE.exists(): 21 print("No notes found.") 22 return 23 24 content = NOTES_FILE.read_text(encoding="utf-8").strip() 25 26 if not content: 27 print("No notes found.") 28 return 29 30 print("\nYour Notes:") 31 print(content) 32 33 34def main(): 35 while True: 36 print("\n1. Add Note") 37 print("2. View Notes") 38 print("3. Exit") 39 40 choice = input("Choose an option: ").strip() 41 42 if choice == "1": 43 add_note() 44 elif choice == "2": 45 view_notes() 46 elif choice == "3": 47 print("Goodbye!") 48 break 49 else: 50 print("Invalid choice. Please try again.") 51 52 53if __name__ == "__main__": 54 main()
This example combines:
- Functions
pathlib- File writing
- File reading
- Input validation
- The
withstatement if __name__ == "__main__"
Practice Project 2: Student Database With CSV
A CSV file can be used to store student records.
1import csv 2from pathlib import Path 3 4STUDENTS_FILE = Path("students.csv") 5 6 7def add_student(): 8 name = input("Student name: ").strip() 9 10 try: 11 marks = float(input("Marks: ")) 12 except ValueError: 13 print("Marks must be a number.") 14 return 15 16 if not 0 <= marks <= 100: 17 print("Marks must be between 0 and 100.") 18 return 19 20 file_exists = STUDENTS_FILE.exists() 21 22 with STUDENTS_FILE.open( 23 "a", 24 newline="", 25 encoding="utf-8", 26 ) as file: 27 writer = csv.writer(file) 28 29 if not file_exists: 30 writer.writerow(["Name", "Marks"]) 31 32 writer.writerow([name, marks]) 33 34 print("Student saved successfully.") 35 36 37def view_students(): 38 if not STUDENTS_FILE.exists(): 39 print("No student records found.") 40 return 41 42 with STUDENTS_FILE.open( 43 "r", 44 newline="", 45 encoding="utf-8", 46 ) as file: 47 reader = csv.DictReader(file) 48 49 for student in reader: 50 print( 51 f"Name: {student['Name']}, " 52 f"Marks: {student['Marks']}" 53 ) 54 55 56def main(): 57 while True: 58 print("\n1. Add Student") 59 print("2. View Students") 60 print("3. Exit") 61 62 choice = input("Choose: ").strip() 63 64 if choice == "1": 65 add_student() 66 elif choice == "2": 67 view_students() 68 elif choice == "3": 69 break 70 else: 71 print("Invalid choice.") 72 73 74if __name__ == "__main__": 75 main()
This is a more realistic example of persistent data storage.
Practice Project 3: JSON User Profile
JSON is useful when the data has multiple fields or nested structures.
1import json 2from pathlib import Path 3 4profile = { 5 "name": "Ankit", 6 "age": 22, 7 "skills": [ 8 "Python", 9 "Docker", 10 "Git", 11 ], 12 "active": True, 13} 14 15file_path = Path("profile.json") 16 17file_path.write_text( 18 json.dumps(profile, indent=4), 19 encoding="utf-8", 20) 21 22print("Profile saved.")
Read the profile:
1data = json.loads( 2 file_path.read_text(encoding="utf-8") 3) 4 5print("Name:", data["name"]) 6print("Skills:", data["skills"])
For straightforward file-based JSON storage, json.dump() and json.load() are often the clearest choices.
Practice Project 4: File Word Counter
Create a program that counts the number of words in a text file.
1from pathlib import Path 2 3file_path = Path("notes.txt") 4 5if not file_path.exists(): 6 print("File not found.") 7else: 8 text = file_path.read_text(encoding="utf-8") 9 words = text.split() 10 11 print("Word count:", len(words))
The split() method separates the text into whitespace-delimited words.
Practice Project 5: Search for a Word
1from pathlib import Path 2 3file_path = Path("notes.txt") 4 5word = input("Search for: ").strip() 6 7if not file_path.exists(): 8 print("File not found.") 9else: 10 text = file_path.read_text(encoding="utf-8") 11 12 if word.lower() in text.lower(): 13 print("Word found.") 14 else: 15 print("Word not found.")
This performs a simple case-insensitive search.
Practice Project 6: File Copy
For a small text file:
1from pathlib import Path 2 3source = Path("source.txt") 4destination = Path("backup.txt") 5 6if not source.exists(): 7 print("Source file not found.") 8else: 9 content = source.read_text(encoding="utf-8") 10 destination.write_text(content, encoding="utf-8") 11 12 print("File copied successfully.")
For arbitrary file types such as images, use binary mode or appropriate filesystem-copy utilities instead of treating the file as text.
Common Exceptions in File Handling
Several exceptions frequently occur when working with files.
| Exception | Common Cause |
|---|---|
FileNotFoundError | File does not exist |
FileExistsError | x mode used for an existing file |
PermissionError | Insufficient permissions |
IsADirectoryError | A directory was used where a file was expected |
UnicodeDecodeError | File encoding does not match the requested decoding |
OSError | General operating-system file error |
You can handle expected errors with try and except.
Example:
1from pathlib import Path 2 3try: 4 content = Path("notes.txt").read_text(encoding="utf-8") 5 print(content) 6 7except FileNotFoundError: 8 print("The file was not found.") 9 10except PermissionError: 11 print("Permission denied.") 12 13except OSError as error: 14 print("File operation failed:", error)
Avoid catching every exception with a bare except: unless you have a specific reason.
Common Mistakes
Forgetting to Close a File
Less ideal:
1file = open("notes.txt", "r", encoding="utf-8") 2 3print(file.read())
Preferred:
1with open("notes.txt", "r", encoding="utf-8") as file: 2 print(file.read())
Using w When You Need a
This overwrites the existing contents:
1with open("notes.txt", "w", encoding="utf-8") as file: 2 file.write("New note\n")
Use append mode when you want to preserve existing content:
1with open("notes.txt", "a", encoding="utf-8") as file: 2 file.write("New note\n")
Reading a Missing File
This can raise:
1with open("data.txt", "r", encoding="utf-8") as file: 2 print(file.read())
If the file does not exist:
1FileNotFoundError
Handle it when appropriate:
1try: 2 with open("data.txt", "r", encoding="utf-8") as file: 3 print(file.read()) 4except FileNotFoundError: 5 print("Data file not found.")
Forgetting Encoding
Instead of relying on the environment's default encoding:
1open("notes.txt", "r")
prefer:
1open("notes.txt", "r", encoding="utf-8")
This makes text-file behavior more predictable across different systems.
Manually Parsing CSV
Avoid doing this:
1with open("students.csv", encoding="utf-8") as file: 2 for line in file: 3 name, marks = line.strip().split(",")
Real CSV files can contain commas, quotes, and escaped values.
Use Python's csv module:
1import csv 2 3with open("students.csv", newline="", encoding="utf-8") as file: 4 reader = csv.reader(file) 5 6 for row in reader: 7 print(row)
File Handling Best Practices
Follow these practices when working with files in Python:
- Prefer
with open(...)for file operations. - Specify
encoding="utf-8"for text files when appropriate. - Use
pathlibfor modern filesystem path handling. - Use
csvfor CSV files instead of manually splitting strings. - Use
jsonfor structured JSON data. - Use binary modes for binary files.
- Validate user input before writing data.
- Handle expected file-related exceptions.
- Avoid accidentally using
wwhen you needa. - Process very large files incrementally rather than loading everything into memory.
- Keep file paths configurable rather than scattering hard-coded paths throughout a project.
- Use descriptive filenames and clear directory structures.
Additional Practice Exercises
Exercise 1: Count Words
Read notes.txt and count the number of words.
Expected concept:
1text.split()
Exercise 2: Count Lines
Count the number of lines in a text file.
Try processing the file line by line rather than loading the entire file into memory.
Exercise 3: Find the Longest Line
Read a text file and find the longest line.
Exercise 4: Copy a Text File
Read source.txt and create a copy named backup.txt.
Exercise 5: Search a File
Ask the user for a word and report whether it appears in notes.txt.
Exercise 6: Student CSV
Create a CSV file containing:
1Name 2Age 3Marks
Store at least five students and display students who scored more than 80 marks.
Exercise 7: JSON Configuration
Create a config.json file containing:
1{ 2 "theme": "dark", 3 "language": "en", 4 "notifications": true 5}
Write a Python program that reads and displays the configuration.
Exercise 8: Log File
Create a program that records application events in a file:
1Application started 2User logged in 3Data processed 4Application closed
Use append mode so previous log entries are preserved.
Quick File Handling Reference
| Operation | Python Example |
|---|---|
| Open/read | open("file.txt", "r") |
| Write | open("file.txt", "w") |
| Append | open("file.txt", "a") |
| Create | open("file.txt", "x") |
| Read all | file.read() |
| Read one line | file.readline() |
| Read lines | file.readlines() |
| Write text | file.write() |
| Write multiple strings | file.writelines() |
| Close | file.close() |
| Recommended cleanup | with open(...) |
| Check path | Path.exists() |
| Read text | Path.read_text() |
| Write text | Path.write_text() |
| CSV | csv.reader() / csv.writer() |
Key Takeaways
After completing this module, you should understand:
- File handling allows Python programs to store and retrieve persistent data.
open()is used to open files.rreads a file.wwrites and overwrites a file.aappends data.xcreates a new file.withautomatically handles file closing.read()reads file content.readline()reads one line.readlines()returns lines as a list.- Iterating directly over a file is useful for processing large text files efficiently.
pathlibprovides a modern way to work with file paths.csvis the recommended standard-library module for CSV data.jsonis useful for structured data.- Binary files should be handled with binary modes such as
rbandwb. tryandexceptcan handle expected file-related errors.- Explicit UTF-8 encoding makes text-file handling more predictable.
- File handling is an essential skill for building real-world Python applications.
Once you understand file handling, you can move toward more advanced topics such as databases, APIs, logging, configuration management, data processing, and persistent application storage.