asyncio异步读写文档
在 asyncio 中保存文件时,如果涉及 阻塞式 I/O 操作(例如写入大文件或频繁读写),可以通过以下两种方式。
使用run_in_executor + 线程池
将同步的阻塞文件操作委托给线程池执行,保持异步事件循环的响应性。
代码示例:
import asyncio
from concurrent.futures import ThreadPoolExecutor
from functools import partial
# 全局线程池(避免重复创建)
_executor = ThreadPoolExecutor(max_workers=4)
async def async_save_file(data: str, filename: str) -> None:
loop = asyncio.get_running_loop()
func = partial(save_file_sync)
# 将同步写入操作提交到线程池
await loop.run_in_executor(
_executor,
func, # 同步函数
*(data, filename)
)
def save_file_sync(data: str, filename: str) -> None:
"""同步保存文件"""
with open(filename, "w", encoding="utf-8") as f:
f.write(data)
print(f"文件 {filename} 保存成功")
# 使用示例
async def main():
await async_save_file("Hello, asyncio!", "test.txt")
asyncio.run(main())
使用异步文件库 aiofiles
通过 aiofiles 库实现异步文件操作(底层基于线程池,但语法更符合异步习惯)。
安装依赖
pip install aiofiles
代码示例:
import asyncio
import aiofiles
async def async_save_file(data: str, filename: str) -> None:
async with aiofiles.open(filename, "w", encoding="utf-8") as f:
await f.write(data)
print(f"文件 {filename} 保存成功")
# 使用示例
async def main():
await async_save_file("Hello, aiofiles!", "test_async.txt")
asyncio.run(main())
备注
两种方式都可以实现异步文件读写操作,这里只给了异步写的示例代码,同理,异步读文件也可以使用类似的方式实现。
相对来说,使用aiofiles,因为封装了接口,所以代码更简洁,更符合异步编程的习惯,两者性能上没有太大的区别,所以如何选择仁者见仁智者见智。
需要特别注意的是不要在异步函数中直接调用同步文件操作(如 open()、f.write()),否则会阻塞事件循环。也要记得使用with 语句或 async with 确保文件句柄正确关闭。