File Handling in Python: Read, Write and Organize Data
Introduction: why reading and writing files is fundamental
Welcome to part 6 of 10 of our Python course for beginners. So far, all the data we have used in our programs disappears when the program ends. If you close the terminal, everything is lost.
For data to persist (be saved permanently), we need to write it to files. Whether it is a text file, a CSV with tabular data, or a JSON with structured data, Python makes working with files simple and safe.

Opening files: the open() function and modes
The open() function is the gateway for working with files in Python. It takes two main parameters: the file name and the mode in which you want to open it.
1# Basic syntax
2file = open("my_file.txt", "r") # open for reading
3# ... do something with the file ...
4file.close() # ALWAYS close the file
Opening modes
| Mode | Description | If file doesn't exist |
|---|---|---|
"r" |
Read — only reading | Raises an error |
"w" |
Write — erases previous content | Creates it |
"a" |
Append — writes at the end without erasing | Creates it |
"r+" |
Read and write | Raises an error |
"w", you will lose all the information it had. If you want to add content without erasing, use "a".
Reading files: read(), readline(), readlines()
Python has 3 main ways to read the content of a file:
read() — read the entire content
1# Let's say we have a file "greeting.txt" with this content:
2# Hello World
3# Welcome to Python
4# This is a text file
5
6file = open("greeting.txt", "r")
7content = file.read() # reads the ENTIRE file as a string
8print(content)
9file.close()
10
11# Output:
12# Hello World
13# Welcome to Python
14# This is a text file
readline() — read one line at a time
1file = open("greeting.txt", "r")
2
3line1 = file.readline() # reads the first line
4print(line1) # Hello World
5
6
7line2 = file.readline() # reads the second line
8print(line2) # Welcome to Python
9
10
11file.close()
readlines() — read all lines as a list
1file = open("greeting.txt", "r")
2lines = file.readlines() # returns a list of lines
3print(lines)
4# ['Hello World\n', 'Welcome to Python\n', 'This is a text file']
5file.close()
6
7# Iterate line by line (most common way)
8file = open("greeting.txt", "r")
9for line in file:
10 print(line.strip()) # strip() removes the \n at the end
11file.close()
strip() when reading lines is very common because it removes whitespace and newline characters (\n) from the beginning and end of the text.
Writing files: write(), writelines()
To write to a file, we open it in mode "w" (write from scratch) or "a" (append to the end).
write() — write a string
1# Create a new file and write content
2file = open("notes.txt", "w")
3file.write("My first note\n")
4file.write("Python is awesome\n")
5file.write("I am learning to write files\n")
6file.close()
7
8# The file "notes.txt" now contains:
9# My first note
10# Python is awesome
11# I am learning to write files
writelines() — write a list of strings
1lines = [
2 "Line 1: Introduction\n",
3 "Line 2: Development\n",
4 "Line 3: Conclusion\n"
5]
6
7file = open("document.txt", "w")
8file.writelines(lines)
9file.close()
Appending content with "a" mode
1# Append to the end of the existing file
2file = open("notes.txt", "a")
3file.write("This line is added at the end\n")
4file.close()
5
6# Now "notes.txt" has 4 lines instead of 3
write() does not add line breaks automatically. You must include \n at the end of each line if you want each piece of text to appear on a separate line.
The with block (context manager): the safe way
Forgetting to close a file with close() can cause problems: data not being saved, locked files, etc. Python has an elegant solution: the with block.
1# WITHOUT with (unsafe — you might forget close())
2file = open("data.txt", "r")
3content = file.read()
4file.close() # if an error occurs before this line, the file stays open
5
6# WITH with (safe — closes automatically)
7with open("data.txt", "r") as file:
8 content = file.read()
9 print(content)
10# Here the file is already closed automatically, even if there was an error
Always use with. It is the recommended and safe way to work with files in Python. The file closes automatically when exiting the block, regardless of whether there were errors.
1# Writing with with
2with open("shopping_list.txt", "w") as file:
3 file.write("1. Milk\n")
4 file.write("2. Bread\n")
5 file.write("3. Eggs\n")
6
7# Reading with with
8with open("shopping_list.txt", "r") as file:
9 for line in file:
10 print(line.strip())
11# 1. Milk
12# 2. Bread
13# 3. Eggs
with open(...) as file: instead of open() + close(). It is safer, cleaner, and shorter.
Working with CSV files
CSV (Comma-Separated Values) files are text files where data is separated by commas. They are very common for exporting data from spreadsheets, databases, etc.
Reading a CSV file
1import csv
2
3# Let's say we have "students.csv":
4# name,age,grade
5# Ana,20,95
6# Luis,22,88
7# Maria,21,92
8
9with open("students.csv", "r") as file:
10 reader = csv.reader(file)
11
12 # Read the header
13 header = next(reader)
14 print(f"Columns: {header}")
15
16 # Read each row
17 for row in reader:
18 name = row[0]
19 age = row[1]
20 grade = row[2]
21 print(f" {name} is {age} years old and scored {grade}")
Reading CSV as dictionaries
1import csv
2
3# DictReader uses the first row as keys
4with open("students.csv", "r") as file:
5 reader = csv.DictReader(file)
6
7 for row in reader:
8 print(f" {row['name']} - Grade: {row['grade']}")
Writing a CSV file
1import csv
2
3students = [
4 ["name", "age", "grade"], # header
5 ["Ana", 20, 95],
6 ["Luis", 22, 88],
7 ["Maria", 21, 92]
8]
9
10with open("students.csv", "w", newline="") as file:
11 writer = csv.writer(file)
12 for row in students:
13 writer.writerow(row)
14
15print("CSV file created successfully.")
newline="" parameter in open() is important when writing CSV on Windows. Without it, you might get extra blank lines between each row.
Working with JSON files
JSON (JavaScript Object Notation) is a very popular text format for storing structured data. It is similar to Python dictionaries, which makes it very natural to work with.
Reading a JSON file
1import json
2
3# Let's say we have "config.json":
4# {
5# "name": "My App",
6# "version": "1.0",
7# "debug": true,
8# "languages": ["es", "en"]
9# }
10
11with open("config.json", "r") as file:
12 data = json.load(file) # converts JSON to a Python dictionary
13
14print(data["name"]) # My App
15print(data["version"]) # 1.0
16print(data["debug"]) # True
17print(data["languages"]) # ['es', 'en']
18print(type(data)) # <class 'dict'>
Writing a JSON file
1import json
2
3config = {
4 "name": "My App",
5 "version": "2.0",
6 "debug": False,
7 "languages": ["es", "en", "fr"],
8 "database": {
9 "host": "localhost",
10 "port": 5432
11 }
12}
13
14with open("config.json", "w") as file:
15 json.dump(config, file, indent=4, ensure_ascii=False)
16 # indent=4 makes the JSON look pretty (with indentation)
17 # ensure_ascii=False allows special characters like accents
18
19print("JSON file saved.")
Converting between JSON and Python
1import json
2
3# From Python dictionary to JSON string
4data = {"name": "Ana", "age": 25}
5json_string = json.dumps(data, indent=2)
6print(json_string)
7# {
8# "name": "Ana",
9# "age": 25
10# }
11
12# From JSON string to Python dictionary
13json_text = '{"city": "Guadalajara", "country": "Mexico"}'
14data = json.loads(json_text)
15print(data["city"]) # Guadalajara
json.load() / json.dump() work with files, while json.loads() / json.dumps() (with the "s" for string) work with strings.
Handling paths with os.path
When working with files, you need to handle paths correctly. The os.path module helps you build paths that work on any operating system (Windows, Mac, Linux).
1import os
2
3# Check if a file exists
4print(os.path.exists("notes.txt")) # True or False
5
6# Get the file name without the path
7print(os.path.basename("/home/user/documents/notes.txt"))
8# notes.txt
9
10# Get only the directory
11print(os.path.dirname("/home/user/documents/notes.txt"))
12# /home/user/documents
13
14# Join paths safely (works on any OS)
15path = os.path.join("documents", "notes", "file.txt")
16print(path) # documents/notes/file.txt (or documents\notes\file.txt on Windows)
17
18# Get the file extension
19name, extension = os.path.splitext("photo.jpg")
20print(name) # photo
21print(extension) # .jpg
22
23# Get the current directory
24print(os.getcwd()) # /home/user/my_project
25
26# Create a directory if it doesn't exist
27if not os.path.exists("data"):
28 os.makedirs("data")
29 print("Directory 'data' created.")
"folder\\file.txt". Always use os.path.join("folder", "file.txt") so your code works correctly on Windows, Mac, and Linux.
Practical example: notes system with JSON
Let's build a notes system that saves and reads data from a JSON file. This is a complete example that combines everything we learned:
1import json
2import os
3from datetime import datetime
4
5NOTES_FILE = "my_notes.json"
6
7def load_notes():
8 """Loads notes from the JSON file."""
9 if os.path.exists(NOTES_FILE):
10 with open(NOTES_FILE, "r") as file:
11 return json.load(file)
12 return [] # if the file doesn't exist, return an empty list
13
14def save_notes(notes):
15 """Saves notes to the JSON file."""
16 with open(NOTES_FILE, "w") as file:
17 json.dump(notes, file, indent=4, ensure_ascii=False)
18
19def add_note(title, content):
20 """Adds a new note."""
21 notes = load_notes()
22 new_note = {
23 "id": len(notes) + 1,
24 "title": title,
25 "content": content,
26 "date": datetime.now().strftime("%Y-%m-%d %H:%M")
27 }
28 notes.append(new_note)
29 save_notes(notes)
30 print(f" Note '{title}' saved successfully.")
31
32def list_notes():
33 """Shows all notes."""
34 notes = load_notes()
35 if not notes:
36 print(" No notes saved.")
37 return
38 print(f" Total notes: {len(notes)}")
39 for note in notes:
40 print(f" [{note['id']}] {note['title']} ({note['date']})")
41
42def view_note(note_id):
43 """Shows the details of a note by its ID."""
44 notes = load_notes()
45 for note in notes:
46 if note["id"] == note_id:
47 print(f" Title: {note['title']}")
48 print(f" Date: {note['date']}")
49 print(f" Content: {note['content']}")
50 return
51 print(f" Note with ID {note_id} not found.")
52
53def delete_note(note_id):
54 """Deletes a note by its ID."""
55 notes = load_notes()
56 filtered_notes = [n for n in notes if n["id"] != note_id]
57 if len(filtered_notes) == len(notes):
58 print(f" Note with ID {note_id} not found.")
59 return
60 save_notes(filtered_notes)
61 print(f" Note with ID {note_id} deleted.")
62
63# Let's test the system
64print("--- Add notes ---")
65add_note("Shopping", "Buy milk, bread and eggs")
66add_note("Python homework", "Finish the file handling exercise")
67add_note("Idea", "Create a program to organize my expenses")
68
69print("\n--- List notes ---")
70list_notes()
71
72print("\n--- View note 2 ---")
73view_note(2)
74
75print("\n--- Delete note 1 ---")
76delete_note(1)
77
78print("\n--- Updated notes ---")
79list_notes()
This program creates a my_notes.json file that looks like this:
1[
2 {
3 "id": 2,
4 "title": "Python homework",
5 "content": "Finish the file handling exercise",
6 "date": "2026-04-05 14:30"
7 },
8 {
9 "id": 3,
10 "title": "Idea",
11 "content": "Create a program to organize my expenses",
12 "date": "2026-04-05 14:30"
13 }
14]
The most important thing about this example is that the notes are saved permanently. You can close the program, turn off your computer, and when you run it again, your notes will still be there.
Summary and next article
In this article we learned everything you need to work with files in Python:
- open() with modes
r,w,ato open files - read(), readline(), readlines() to read content
- write(), writelines() to write content
- with (context manager) to handle files safely
- csv to read and write CSV files
- json to work with structured data in JSON
- os.path to handle file paths correctly
Comments
Sign in to leave a comment
No comments yet. Be the first!