aiofiles是python中实现异步文件i/o的主流方案,通过线程池封装阻塞式系统调用,因内核级异步磁盘i/o尚未被python标准库支持。

Python 标准库中没有原生支持异步文件 I/O 的模块,aiofiles 是目前最成熟、被广泛采用的第三方方案,它通过线程池(默认使用 concurrent.futures.ThreadPoolExecutor)将阻塞式文件操作“伪装”为协程,再交由事件循环调度,从而实现与 asyncio 生态的无缝集成。
为什么不能直接用 async/await 操作磁盘
操作系统内核层面的文件读写(如 open/read/write)本质上是同步阻塞系统调用。即使在支持 io_uring(Linux 5.1+)或 OVERLAPPED(Windows)的现代系统上,Python 解释器也尚未将其暴露为标准异步 API。因此,真正的“零拷贝异步磁盘 I/O”在当前 Python 生态中并不可用,aiofiles 的线程池封装是务实且高效的选择。
aiofiles 基础配置与最佳实践
安装后即可使用:
pip install aiofiles基本用法示例:
import aiofiles
import asyncio
async def read_file(path):
async with aiofiles.open(path, mode='r', encoding='utf-8') as f:
content = await f.read()
return content
async def write_file(path, data):
async with aiofiles.open(path, mode='w', encoding='utf-8') as f:
await f.write(data)
关键点:
- 始终用
async with管理文件句柄,确保资源及时释放 - 显式指定
encoding,避免依赖平台默认编码引发乱码 - 不要在协程中混用
open()和aiofiles.open(),二者句柄不兼容
事件循环调优:线程池与并发控制
aiofiles 默认复用全局线程池,但高并发读写场景下需主动配置:
from concurrent.futures import ThreadPoolExecutor
import asyncio
import aiofiles
# 自定义线程池,限制最大线程数为 8
executor = ThreadPoolExecutor(max_workers=8)
async def safe_read(path):
loop = asyncio.get_running_loop()
# 显式提交到指定线程池
return await loop.run_in_executor(executor, lambda: open(path).read())
更推荐方式是配置 aiofiles 全局默认执行器:
aiofiles.os.set_event_loop_policy(asyncio.DefaultEventLoopPolicy())
aiofiles.threadpool.set_default_executor(executor)
这样后续所有 aiofiles.open 都会走该线程池,避免默认池无节制增长导致线程耗尽。
与网络请求协同调度:避免 I/O 类型失衡
混合使用 aiohttp(网络)和 aiofiles(磁盘)时,常见误区是让大量磁盘操作抢占事件循环资源。建议:
- 对批量写入做合并:例如将多条日志先缓存在内存 list 中,每 100 条或每秒 flush 一次,而非每条都
await write() - 读取大文件时分块(chunk)处理:
await f.read(8192),防止单次协程阻塞过久 - 若磁盘 I/O 成为瓶颈,优先考虑优化存储介质(如 SSD)、调整文件系统挂载参数,而非仅靠 asyncio 调优
不复杂但容易忽略:磁盘速度远低于内存和网络带宽,异步化收益有限;真正需要极致性能的场景,应转向内存映射(mmap)或专用存储服务。










