How to work with files in Python

Learn how to work with files in Python. This guide covers methods, tips, real-world examples, and common error debugging for your projects.

How to work with files in Python
Published on: 
Mon
Apr 6, 2026
Updated on: 
Wed
Apr 8, 2026
The Replit Team

File manipulation in Python is a fundamental skill for developers. It lets you read, write, and manage data for applications, scripts, and automated processes with simple, built-in functions.

In this article, we'll cover essential techniques and practical tips for file handling. You'll explore real-world applications and learn common debugging strategies to help you manage files in your Python projects effectively.

Basic file reading and writing with open()

# Write to a file
with open('example.txt', 'w') as file:
file.write('Hello, Python!')

# Read from a file
with open('example.txt', 'r') as file:
content = file.read()
print(content)--OUTPUT--Hello, Python!

The with statement is the preferred way to work with files. It automatically closes the file for you once the block is finished, which prevents resource leaks and makes your code cleaner and safer, even if errors occur. You don't need to manually call file.close().

The second argument in the open() function sets the mode. Using 'w' opens a file for writing, creating it if it doesn't exist or overwriting it if it does. The 'r' mode opens a file for reading its contents.

Common file operations

Beyond the basic read() and write() methods, Python offers more granular control for reading line by line, appending content, and managing file paths.

Reading files line by line

with open('example.txt', 'w') as file:
file.write('Line 1\nLine 2\nLine 3')

with open('example.txt', 'r') as file:
for line in file:
print(line.strip())--OUTPUT--Line 1
Line 2
Line 3

When you need to process a file one line at a time, you can iterate directly over the file object. This approach is memory-efficient because it reads the file progressively instead of loading it all at once, which is ideal for large files.

  • Each line you get from the loop includes the trailing newline character (\n).
  • Use the strip() method to remove this character and any other leading or trailing whitespace for cleaner data.

Writing and appending to files

# Write to a new file
with open('data.txt', 'w') as file:
file.write('First line\n')

# Append to existing file
with open('data.txt', 'a') as file:
file.write('Second line\n')
file.write('Third line\n')

with open('data.txt', 'r') as file:
print(file.read())--OUTPUT--First line
Second line
Third line

While the 'w' mode is useful for creating files, it overwrites existing content. To add data to a file without erasing it, you'll want to use append mode. Opening a file with 'a' moves the cursor to the end, so anything you write gets added on.

  • 'w' (write): Creates a new file or overwrites an existing one.
  • 'a' (append): Adds content to the end of an existing file. If the file doesn't exist, it creates it.

Working with file paths using pathlib

from pathlib import Path

# Create a Path object
path = Path('documents/notes.txt')

# Create parent directories if they don't exist
path.parent.mkdir(parents=True, exist_ok=True)

# Write to the file
path.write_text('Notes content')

# Read from the file
content = path.read_text()
print(f"File content: {content}")
print(f"File exists: {path.exists()}")--OUTPUT--File content: Notes content
File exists: True

The pathlib module provides a modern, object-oriented way to handle file system paths. Instead of manipulating strings, you work with Path objects, which makes your code more readable and reliable across different operating systems.

  • The path.parent.mkdir(parents=True, exist_ok=True) command is a safe way to create parent directories without errors if they already exist.
  • Methods like write_text() and read_text() are convenient shortcuts that handle opening and closing files for you.
  • You can check for a file’s presence with path.exists().

Advanced file techniques

With the basics covered, you're ready for advanced tasks like working with binary files, navigating with seek() and tell(), and managing directories with shutil.

Working with binary files

# Write binary data
data = bytes([65, 66, 67, 68, 69]) # ASCII values for ABCDE
with open('binary.dat', 'wb') as file:
file.write(data)

# Read binary data
with open('binary.dat', 'rb') as file:
binary_data = file.read()
print(binary_data)
print(binary_data.decode('ascii'))--OUTPUT--b'ABCDE'
ABCDE

Not all files are plain text. When you're handling data like images, audio, or executables, you need to work in binary mode. You can do this by simply adding a 'b' to the mode string in the open() function.

  • 'wb' (write binary) lets you write bytes objects directly to a file.
  • 'rb' (read binary) reads the file's raw byte content.

Reading a binary file gives you a bytes object, not a string. To convert this data back into human-readable text, you'll need to decode() it using the correct character encoding.

Using file objects with seek() and tell()

with open('positions.txt', 'w') as file:
file.write('Python is amazing!')

with open('positions.txt', 'r') as file:
# Get current position
print(f"Initial position: {file.tell()}")

# Read first 6 characters
print(file.read(6))

# Move to position 10
file.seek(10)
print(f"New position: {file.tell()}")
print(file.read())--OUTPUT--Initial position: 0
Python
New position: 10
amazing!

The seek() and tell() methods give you precise control over where you read or write within a file. Think of it like moving a cursor in a text document. The tell() method shows the cursor's current byte position, while seek() moves it to a new one. This is useful for jumping to specific parts of a file without reading everything sequentially.

  • tell(): Returns the current position in bytes.
  • seek(offset): Moves the cursor to the byte specified by the offset.

File operations with shutil library

import shutil
import os

# Create a file
with open('original.txt', 'w') as file:
file.write('Original content')

# Copy the file
shutil.copy('original.txt', 'copied.txt')

# Check both files
for filename in ['original.txt', 'copied.txt']:
with open(filename, 'r') as file:
print(f"{filename}: {file.read()}")--OUTPUT--original.txt: Original content
copied.txt: Original content

When you need to manage files and directories, the shutil module provides high-level functions for operations like copying, moving, and deleting. In the example, shutil.copy() duplicates a file from a source to a destination path. This is far more efficient than manually reading and writing the data yourself.

  • Other useful functions include shutil.move() for relocating files and shutil.rmtree() for deleting entire directory trees.

Move faster with Replit

Replit is an AI-powered development platform that comes with all Python dependencies pre-installed, so you can skip setup and start coding instantly. This environment helps you move from learning individual techniques to building complete applications with Agent 4.

Instead of piecing together file operations, you can describe the app you want to build, and Agent will handle the code, databases, APIs, and deployment. For example, you could create:

  • A file organizer that reads a directory and uses shutil.move() to sort documents into folders based on their extension.
  • A log consolidator that iterates through multiple text files, extracts error messages, and appends them to a single daily report.
  • A backup utility that uses shutil.copy() to duplicate important files to an archive folder.

Simply describe your app, and Replit will write the code, test it, and fix issues automatically, all within your browser.

Common errors and challenges

Working with files in Python can sometimes lead to errors, but most are easy to fix once you know what to look for.

Handling file not found errors with try-except

One of the most common issues is the FileNotFoundError. This error pops up when your script tries to open a file that doesn't exist at the specified path. Instead of letting your program crash, you can handle it gracefully using a try-except block.

By wrapping your file operation in a try statement, you can catch the error with an except FileNotFoundError: clause. This gives you a chance to inform the user the file is missing, create a default file, or simply log the issue without halting execution.

Solving encoding issues with non-ASCII text

If you've ever seen garbled text or a UnicodeDecodeError, you've run into an encoding issue. This happens when a file contains non-ASCII characters—like accents, symbols, or emojis—and Python tries to read it using the wrong text encoding.

The solution is to explicitly tell Python which encoding to use. When you open the file, add the encoding argument, like this: open('data.txt', 'r', encoding='utf-8'). Using 'utf-8' is a robust choice as it supports a vast range of characters and is a standard for web and text files.

Fixing file mode errors when reading or writing

An io.UnsupportedOperation error means you're trying to do something the file wasn't opened for, such as writing to a file opened in read-only mode. This is a simple mix-up between your intent and the mode you passed to the open() function.

Always double-check your file mode to make sure it aligns with your goal:

  • Use 'r' to read, 'w' to write (and overwrite), and 'a' to append.
  • If you need to both read and write, you can use a mode like 'r+', which allows both operations without erasing the file first.

Handling file not found errors with try-except

A FileNotFoundError is a common roadblock that occurs when your script can't locate a file. Without any error handling, your program will crash immediately. The following example shows what happens when you try to read a nonexistent file.

# This will crash if the file doesn't exist
with open('nonexistent_file.txt', 'r') as file:
content = file.read()
print(content)

The script attempts to open nonexistent_file.txt in read mode ('r'), but since the file doesn't exist, Python raises an error and stops. The following example shows how you can prevent the crash and manage the error gracefully.

# Using try-except to handle missing files gracefully
try:
with open('nonexistent_file.txt', 'r') as file:
content = file.read()
print(content)
except FileNotFoundError:
print("Error: The file does not exist")

By wrapping the file operation in a try block, you tell Python to attempt the code inside. If a FileNotFoundError occurs, the program doesn't crash. Instead, it jumps to the except block and runs that code, letting you handle the error gracefully. This is essential when dealing with files that might be missing or when working with user-provided file paths, as it keeps your application running smoothly.

Solving encoding issues with non-ASCII text

When your file contains non-ASCII characters, like the Chinese characters in '世界', Python can't always read them without the right instructions. This mismatch often results in a UnicodeDecodeError. The following code demonstrates what happens when an encoding isn't specified.

# This might raise UnicodeDecodeError with special characters
with open('unicode_file.txt', 'w') as file:
file.write('Hello, 世界!')

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

The error happens because the default text encoding used to read the file can't interpret the non-ASCII characters '世界'. Python needs to be told explicitly which encoding to use. The following example shows how to prevent this error.

# Explicitly specify encoding for files with non-ASCII characters
with open('unicode_file.txt', 'w', encoding='utf-8') as file:
file.write('Hello, 世界!')

with open('unicode_file.txt', 'r', encoding='utf-8') as file:
content = file.read()
print(content)

By adding the encoding='utf-8' argument to the open() function, you explicitly tell Python how to interpret the file's contents. This prevents a UnicodeDecodeError by ensuring special characters are read correctly. You should always consider specifying the encoding when working with text files from external sources, such as APIs or user uploads, as they often contain non-ASCII characters. This simple addition makes your code more robust and reliable.

Fixing file mode errors when reading or writing

An io.UnsupportedOperation error is a classic mix-up, signaling that you're trying to perform an action on a file opened in the wrong mode. For instance, you might try writing to a file opened with 'r'. The code below shows this error in action.

# This will raise an error - trying to write in read mode
with open('example.txt', 'r') as file:
file.write('This will fail!')

The script opens the file in read-only mode ('r'), so the subsequent attempt to add text with file.write() fails. This mismatch is what causes the error. The following example shows how to fix this.

# Use the correct mode for the intended operation
with open('example.txt', 'w') as file:
file.write('This will work!')

The fix is simple: use the correct file mode for your operation. By opening the file with 'w', you're telling Python you intend to write, which resolves the error. This kind of issue often pops up when you copy and paste code without adjusting the mode string in the open() function. Always double-check that your mode matches the action you want to perform to prevent these errors from crashing your script.

Real-world applications

Moving beyond troubleshooting, you can apply these file handling skills to build practical features like a simple logging system or a settings manager.

Creating a simple logging system with open()

You can build a simple logging system by using open() in append mode, which lets you add new records to a file without erasing what's already there.

def log_event(event_type, message):
with open('app_log.txt', 'a') as log_file:
log_file.write(f"{event_type}: {message}\n")

log_event("INFO", "Application started")
log_event("ERROR", "Failed to connect to database")

with open('app_log.txt', 'r') as log_file:
print(log_file.read())

This log_event function offers a straightforward way to record application activity. It takes an event type and a message, then appends them as a formatted line to app_log.txt.

  • The function uses append mode ('a') to ensure new entries are added to the end of the file, preserving the existing log history.
  • Adding a newline character (\n) at the end of each write operation keeps the log organized and readable, with one entry per line.

This creates a simple yet effective chronological record of events.

Storing and retrieving application settings with json

When your application needs to remember user preferences, the json module offers a straightforward way to save and retrieve settings from a simple text file.

import json

# Save settings to a JSON file
settings = {"theme": "dark", "font_size": 12, "notifications": True}
with open('settings.json', 'w') as file:
json.dump(settings, file)

# Read settings from the JSON file
with open('settings.json', 'r') as file:
loaded_settings = json.load(file)
print(f"Theme: {loaded_settings['theme']}, Font Size: {loaded_settings['font_size']}")

The json module bridges the gap between Python objects and the universal JSON data format, making your data portable. It effectively translates complex Python data structures into a simple text-based format that can be easily stored or transmitted.

  • The json.dump() function serializes a Python object, like the settings dictionary, into a JSON string and writes it to a file.
  • Conversely, json.load() reads a file containing JSON data and deserializes it back into a Python object, letting you use it natively again.

Get started with Replit

Now, turn these skills into a working tool. Describe what you want to build to Replit Agent, like "create a log analyzer that counts errors in a text file" or "build a utility that sorts files by extension."

It writes the code, tests for errors, and deploys your app directly from your instructions. Start building with Replit.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.