Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes
Python

Async File I/O in Python with aiofiles

Learn how to perform non-blocking file operations in Python using aiofiles. This guide covers installation, real-world examples for concurrent file processing, logging, and copies, plus performance tips to keep your async code truly non-blocking.

July 2026 9 min read 2 views 0 hearts

Mastering Asynchronous File I/O in Python with aiofiles

When I first started working with asynchronous Python, I quickly realized that not everything plays nicely with async and await. Network requests? No problem. Database queries? Absolutely. But file operations? That's where things get tricky. The standard open() function blocks your entire event loop, which defeats the purpose of going async in the first place.

That's where aiofiles comes in. Let me show you how to handle file operations without blocking your event loop.

Why Regular File I/O Is a Problem in Async Code

Imagine you're building a web scraper that needs to save thousands of HTML files. With regular synchronous file operations, each write blocks your entire application. Even if you're using asyncio for network requests, the moment you try to save a file, everything pauses.

Here's what happens under the hood: - Standard file operations use the operating system's blocking I/O - The event loop can't do anything else while waiting for disk operations - Your carefully crafted async code becomes synchronous at the file level

Getting Started with aiofiles

First, install the library:

pip install aiofiles

Now you can use it just like open(), but with await:

import asyncio
import aiofiles

async def read_file_async():
    async with aiofiles.open('data.txt', mode='r') as f:
        contents = await f.read()
        return contents

async def write_file_async():
    async with aiofiles.open('output.txt', mode='w') as f:
        await f.write('Hello from PythonSkillset!')

Real-World Examples

Example 1: Processing Multiple Files Concurrently

Let's say you need to read several configuration files at startup. Instead of reading them one by one, you can read them all at once:

import asyncio
import aiofiles

async def read_config(filename):
    async with aiofiles.open(filename, 'r') as f:
        content = await f.read()
        return {filename: content}

async def load_all_configs():
    files = ['config1.json', 'config2.json', 'config3.json']
    tasks = [read_config(f) for f in files]
    results = await asyncio.gather(*tasks)
    return results

# Run it
configs = asyncio.run(load_all_configs())

Example 2: Logging Without Blocking

A common scenario at PythonSkillset is handling high-volume logging. Here's how you'd implement non-blocking logging:

import asyncio
import aiofiles
from datetime import datetime

class AsyncLogger:
    def __init__(self, logfile='app.log'):
        self.logfile = logfile

    async def log(self, message):
        timestamp = datetime.now().isoformat()
        log_entry = f"[{timestamp}] {message}\n"
        async with aiofiles.open(self.logfile, mode='a') as f:
            await f.write(log_entry)

    async def read_logs(self):
        async with aiofiles.open(self.logfile, mode='r') as f:
            return await f.readlines()

# Usage in an async context
logger = AsyncLogger()
await logger.log("User logged in successfully")
await logger.log("Data processing started")

Example 3: File Copy Made Efficient

Need to copy large files without freezing your application? Here's how:

import asyncio
import aiofiles

async def copy_file(source, destination, chunk_size=8192):
    async with aiofiles.open(source, mode='rb') as src:
        async with aiofiles.open(destination, mode='wb') as dst:
            while True:
                chunk = await src.read(chunk_size)
                if not chunk:
                    break
                await dst.write(chunk)

async def copy_multiple_files(file_pairs):
    tasks = [copy_file(src, dst) for src, dst in file_pairs]
    await asyncio.gather(*tasks)

Working with Different File Modes

aiofiles supports all the modes you're used to:

# Binary mode for images or zip files
async with aiofiles.open('image.png', mode='rb') as f:
    data = await f.read()

# Appending to existing files
async with aiofiles.open('server.log', mode='a') as f:
    await f.write('New log entry\n')

# Reading and writing in the same context
async with aiofiles.open('editor.txt', mode='r+') as f:
    content = await f.read()
    await f.seek(0)
    await f.write(content.replace('old', 'new'))

Performance Tips from PythonSkillset

After working with aiofiles on several projects, here's what I've learned:

  1. Don't make every file operation async - If you're reading small files (under a few KB), the overhead of async might not be worth it. Use sync for small, quick operations.

  2. Batch your writes - Instead of writing to the same file 1000 times, buffer the content and write it all at once:

async def batch_write(lines, filename):
    buffer = "\n".join(lines)
    async with aiofiles.open(filename, mode='w') as f:
        await f.write(buffer)
  1. Use context managers always - Forgetting async with means your file won't close properly, leading to resource leaks.

  2. Consider using aiofiles for temp files too - Temporary file operations benefit from async just as much as permanent ones.

When Not to Use aiofiles

Let's be honest: aiofiles isn't always the answer. Here's when you should stick with regular files: - Reading or writing single configuration files at startup - Processing files only once during script execution - Working with very small files (under 100 bytes) - Simple scripts where async isn't used anywhere else

The Bottom Line

aiofiles fills an important gap in Python's async ecosystem. It lets you handle file operations the same way you handle network requests - without blocking your event loop. When you're building high-performance async applications, especially ones that process many files simultaneously, this library is indispensable.

Remember, the goal isn't to make everything async. It's to make sure that when you do use async, nothing blocks your event loop. And aiofiles does exactly that for file operations.

Comments

Questions, corrections, and tips stay visible for everyone reading this page.

0 in thread

Join the discussion

Shown next to your comment.

Up to 4,000 characters

No comments yet

Be the first to leave a note — it helps the next reader.