Python File Handling

Learn how to work with files in Python, including reading, writing, and manipulating different file types. This guide covers text files, CSV files, JSON files, and binary files.

File Operations Basics

Python provides built-in functions for file operations. The main function is open(), which returns a file object.

Opening Files

# Basic syntax
file = open('filename.txt', 'mode')

# Common modes
# 'r' - Read (default)
# 'w' - Write (overwrites existing file)
# 'a' - Append (adds to existing file)
# 'b' - Binary mode
# '+' - Read and write

The with Statement (Recommended)

Always use the with statement for file operations as it automatically handles closing the file:

# Reading a file
with open('example.txt', 'r') as file:
    content = file.read()
    print(content)

# File is automatically closed here

Reading Text Files

Reading Entire File

with open('data.txt', 'r') as file:
    content = file.read()
    print(content)

Reading Line by Line

with open('data.txt', 'r') as file:
    for line in file:
        print(line.strip())  # Remove newline character

Reading All Lines into List

with open('data.txt', 'r') as file:
    lines = file.readlines()
    
for line in lines:
    print(line.strip())

Reading First Few Lines

def read_first_lines(filename, num_lines):
    """Read first n lines from a file"""
    with open(filename, 'r') as file:
        lines = []
        for i, line in enumerate(file):
            if i >= num_lines:
                break
            lines.append(line.strip())
        return lines

# Usage
first_lines = read_first_lines('data.txt', 5)
for line in first_lines:
    print(line)

Writing Text Files

Writing to a File

# This overwrites the file if it exists
with open('output.txt', 'w') as file:
    file.write('Hello, World!\n')
    file.write('This is a new line.\n')

Appending to a File

# This adds to the end of the file
with open('output.txt', 'a') as file:
    file.write('This line is appended.\n')

Writing Multiple Lines

lines = [
    'Line 1\n',
    'Line 2\n',
    'Line 3\n'
]

with open('output.txt', 'w') as file:
    file.writelines(lines)

Working with CSV Files

Reading CSV Files

import csv

# Method 1: Using csv.reader
with open('data.csv', 'r') as file:
    reader = csv.reader(file)
    for row in reader:
        print(row)  # Each row is a list

# Method 2: Using csv.DictReader (more readable)
with open('data.csv', 'r') as file:
    reader = csv.DictReader(file)
    for row in reader:
        print(f"Name: {row['name']}, Age: {row['age']}")

Writing CSV Files

import csv

# Method 1: Using csv.writer
data = [
    ['Name', 'Age', 'City'],
    ['John', 25, 'New York'],
    ['Jane', 30, 'Los Angeles']
]

with open('output.csv', 'w', newline='') as file:
    writer = csv.writer(file)
    writer.writerows(data)

# Method 2: Using csv.DictWriter
data = [
    {'name': 'John', 'age': 25, 'city': 'New York'},
    {'name': 'Jane', 'age': 30, 'city': 'Los Angeles'}
]

with open('output.csv', 'w', newline='') as file:
    fieldnames = ['name', 'age', 'city']
    writer = csv.DictWriter(file, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerows(data)

Working with JSON Files

Reading JSON Files

import json

with open('data.json', 'r') as file:
    data = json.load(file)
    print(data)

# Access JSON data
print(f"Name: {data['name']}")
print(f"Items: {data['items']}")

Writing JSON Files

import json

data = {
    'name': 'John Doe',
    'age': 30,
    'items': ['item1', 'item2', 'item3'],
    'active': True
}

with open('output.json', 'w') as file:
    json.dump(data, file, indent=2)  # indent for pretty printing

Pretty JSON Output

import json

data = {'name': 'John', 'age': 30}

# Write with nice formatting
with open('pretty.json', 'w') as file:
    json.dump(data, file, indent=4, sort_keys=True)

Binary Files

Reading Binary Files

# Read image file
with open('image.jpg', 'rb') as file:
    binary_data = file.read()
    print(f"File size: {len(binary_data)} bytes")

Writing Binary Files

# Copy binary file
with open('source.jpg', 'rb') as source_file:
    binary_data = source_file.read()

with open('copy.jpg', 'wb') as dest_file:
    dest_file.write(binary_data)

File and Directory Operations

Checking File Existence

import os

if os.path.exists('data.txt'):
    print('File exists')
else:
    print('File does not exist')

# Check if it's a file
if os.path.isfile('data.txt'):
    print('This is a file')

# Check if it's a directory
if os.path.isdir('my_folder'):
    print('This is a directory')

Getting File Information

import os
import datetime

filename = 'data.txt'

if os.path.exists(filename):
    # File size
    size = os.path.getsize(filename)
    print(f"File size: {size} bytes")
    
    # Modification time
    mod_time = os.path.getmtime(filename)
    mod_date = datetime.datetime.fromtimestamp(mod_time)
    print(f"Last modified: {mod_date}")
    
    # File extension
    _, ext = os.path.splitext(filename)
    print(f"File extension: {ext}")

Creating Directories

import os

# Create single directory
os.makedirs('new_folder', exist_ok=True)

# Create nested directories
os.makedirs('path/to/nested/folder', exist_ok=True)

Listing Files in Directory

import os

# List all files and directories
for item in os.listdir('.'):
    print(item)

# List only files
for item in os.listdir('.'):
    if os.path.isfile(item):
        print(f"File: {item}")

# List only directories
for item in os.listdir('.'):
    if os.path.isdir(item):
        print(f"Directory: {item}")

Practical Examples

Log File Reader

def read_log_file(filename, error_only=False):
    """Read and parse a log file"""
    with open(filename, 'r') as file:
        for line in file:
            if error_only and 'ERROR' not in line:
                continue
            
            # Simple log parsing
            parts = line.strip().split()
            if len(parts) >= 4:
                timestamp = ' '.join(parts[:2])
                level = parts[2]
                message = ' '.join(parts[3:])
                
                print(f"{timestamp} [{level}] {message}")

# Usage
read_log_file('app.log', error_only=True)

Configuration File Parser

def parse_config(filename):
    """Parse a simple key=value config file"""
    config = {}
    
    with open(filename, 'r') as file:
        for line in file:
            line = line.strip()
            
            # Skip comments and empty lines
            if not line or line.startswith('#'):
                continue
            
            # Parse key=value pairs
            if '=' in line:
                key, value = line.split('=', 1)
                config[key.strip()] = value.strip()
    
    return config

# Usage
config = parse_config('settings.ini')
print(f"Database: {config.get('database')}")
print(f"Port: {config.get('port')}")

Data Processor

import csv
import json

def csv_to_json(csv_file, json_file):
    """Convert CSV file to JSON format"""
    data = []
    
    with open(csv_file, 'r') as file:
        reader = csv.DictReader(file)
        for row in reader:
            # Convert numeric strings to numbers
            for key, value in row.items():
                try:
                    if '.' in value:
                        row[key] = float(value)
                    else:
                        row[key] = int(value)
                except ValueError:
                    pass  # Keep as string
            
            data.append(row)
    
    with open(json_file, 'w') as file:
        json.dump(data, file, indent=2)
    
    return data

# Usage
data = csv_to_json('users.csv', 'users.json')
print(f"Converted {len(data)} records")

Error Handling

Common File Errors

try:
    with open('nonexistent.txt', 'r') as file:
        content = file.read()
except FileNotFoundError:
    print("File not found!")
except PermissionError:
    print("Permission denied!")
except IOError as e:
    print(f"I/O error: {e}")

# Safe file reading
def safe_read_file(filename):
    """Safely read a file with error handling"""
    try:
        with open(filename, 'r') as file:
            return file.read()
    except FileNotFoundError:
        print(f"Error: File '{filename}' not found")
        return None
    except PermissionError:
        print(f"Error: No permission to read '{filename}'")
        return None
    except Exception as e:
        print(f"Error reading file: {e}")
        return None

Best Practices

  1. Always use with statement - Ensures files are properly closed
  2. Handle exceptions - Use try-catch for file operations
  3. Check file existence - Use os.path.exists() before opening
  4. Use appropriate modes - Choose correct file mode for your operation
  5. Handle encoding - Specify encoding when needed: open('file.txt', 'r', encoding='utf-8')
  6. Close files properly - Let with handle it or close manually
  7. Use pathlib - For modern, object-oriented file path handling

Modern File Handling with pathlib

from pathlib import Path

# Create Path objects
file_path = Path('data/example.txt')
dir_path = Path('data/')

# Check existence
if file_path.exists():
    print("File exists")

# Read file
content = file_path.read_text()

# Write file
file_path.write_text("Hello, pathlib!")

# Create directory
dir_path.mkdir(exist_ok=True)

# List files
for file in dir_path.glob('*.txt'):
    print(file.name)

Next Steps

Explore Python web development to build applications that work with files and data.

External Resources