Reading and Writing Text Files
File handling is a fundamental skill in Python. The built-in open() function provides a clean interface for reading and writing files. Always use the with statement (context manager) to ensure files are properly closed, even if an exception occurs.
# Writing to a file
with open("output.txt", "w") as f:
f.write("Hello, World!\n")
f.write("Second line\n")
# Writing multiple lines
lines = ["Line 1\n", "Line 2\n", "Line 3\n"]
with open("output.txt", "w") as f:
f.writelines(lines)
# Reading entire file
with open("output.txt", "r") as f:
content = f.read()
print(content)
# Reading line by line (memory efficient for large files)
with open("output.txt", "r") as f:
for line in f:
print(line.strip()) # strip() removes trailing newline
# Reading all lines into a list
with open("output.txt", "r") as f:
lines = f.readlines()
print(lines) # ['Line 1\n', 'Line 2\n', 'Line 3\n']
# Appending to a file
with open("output.txt", "a") as f:
f.write("Appended line\n")
# Reading with encoding
with open("unicode.txt", "r", encoding="utf-8") as f:
content = f.read()
Working with CSV Files
The csv module provides robust CSV reading and writing that handles edge cases like quoted fields, different delimiters, and embedded newlines. For large-scale data work, consider using pandas instead.
import csv
# Writing CSV
data = [
["Name", "Age", "City"],
["Alice", 30, "New York"],
["Bob", 25, "London"],
["Charlie", 35, "Tokyo"],
]
with open("people.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerows(data)
# Reading CSV
with open("people.csv", "r") as f:
reader = csv.reader(f)
header = next(reader) # Skip header
for row in reader:
name, age, city = row
print(f"{name} is {age} from {city}")
# DictReader/DictWriter (more readable)
with open("people.csv", "r") as f:
reader = csv.DictReader(f)
for row in reader:
print(f"{row['Name']} lives in {row['City']}")
# Writing with DictWriter
with open("output.csv", "w", newline="") as f:
fieldnames = ["name", "email", "role"]
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerow({"name": "Alice", "email": "alice@test.com", "role": "Engineer"})
Working with JSON
JSON is the lingua franca of APIs and configuration files. Python's json module makes it easy to serialize Python objects to JSON and deserialize JSON back to Python objects.
import json
# Python to JSON
data = {
"name": "Alice",
"age": 30,
"hobbies": ["reading", "coding", "hiking"],
"address": {
"city": "New York",
"country": "USA"
},
"active": True,
"score": None
}
# Write JSON to file
with open("data.json", "w") as f:
json.dump(data, f, indent=2)
# Read JSON from file
with open("data.json", "r") as f:
loaded = json.load(f)
print(loaded["name"]) # "Alice"
# Convert to/from JSON strings
json_string = json.dumps(data, indent=2)
parsed = json.loads(json_string)
# Custom serialization for unsupported types
from datetime import datetime
class DateEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
return super().default(obj)
data_with_date = {"created": datetime.now()}
print(json.dumps(data_with_date, cls=DateEncoder))
Path Handling with pathlib
The pathlib module (Python 3.4+) provides an object-oriented interface for filesystem paths. It is more readable and less error-prone than using string manipulation with os.path.
from pathlib import Path
# Creating paths
home = Path.home()
project = Path("/Users/alice/projects/myapp")
config = project / "config" / "settings.json" # Join with /
# Path properties
print(config.name) # "settings.json"
print(config.stem) # "settings"
print(config.suffix) # ".json"
print(config.parent) # /Users/alice/projects/myapp/config
# Check existence
print(config.exists())
print(config.is_file())
print(config.is_dir())
# Reading and writing (convenience methods)
path = Path("example.txt")
path.write_text("Hello, World!")
content = path.read_text()
path.write_bytes(b"\x00\x01\x02")
data = path.read_bytes()
# Directory operations
src = Path("src")
src.mkdir(parents=True, exist_ok=True)
# Iterate over directory contents
for item in Path(".").iterdir():
print(item.name)
# Glob pattern matching
for py_file in Path(".").glob("**/*.py"):
print(py_file)
# Rename and delete
path.rename("new_name.txt")
# path.unlink() # Delete file
Key Takeaways
- Always use 'with': Context managers ensure files are properly closed
- Use pathlib: Prefer Path objects over os.path string manipulation
- csv module: Use DictReader/DictWriter for readable CSV processing
- json module: Use json.dump/load for files, json.dumps/loads for strings