Ответ
Стандартные файловые операции в Python (open, read, write) являются блокирующими. Их прямой вызов в asyncio коде заморозит весь цикл событий (event loop), сводя на нет преимущества асинхронности.
Для корректной асинхронной работы с файлами существуют два основных подхода:
1. Использование библиотеки aiofiles
Это рекомендуемый и идиоматичный способ. Библиотека предоставляет асинхронный API, который полностью совместим с синтаксисом async/await и не блокирует event loop.
Пример:
import asyncio
import aiofiles
async def main():
async with aiofiles.open('example.txt', mode='w') as f:
await f.write('Hello, aiofiles!')
async with aiofiles.open('example.txt', mode='r') as f:
content = await f.read()
print(content)
asyncio.run(main())
2. Использование loop.run_in_executor
Этот метод позволяет выполнить любую блокирующую (синхронную) функцию в отдельном потоке из пула потоков, не блокируя основной цикл событий. Это универсальный способ для интеграции любого синхронного кода в асинхронный.
Пример:
import asyncio
async def read_file_in_executor():
loop = asyncio.get_running_loop()
# Открываем файл синхронно
with open('example.txt', 'r') as f:
# Выполняем блокирующую операцию f.read() в пуле потоков
content = await loop.run_in_executor(None, f.read)
print(content)
# Для записи файла нужно обернуть в функцию
def write_sync(content):
with open('example.txt', 'w') as f:
f.write(content)
async def main():
loop = asyncio.get_running_loop()
await loop.run_in_executor(None, write_sync, 'Hello, executor!')
await read_file_in_executor()
asyncio.run(main())
Рекомендация: Всегда отдавайте предпочтение aiofiles для работы с файлами в asyncio, так как это более чистый, читаемый и оптимизированный подход. run_in_executor является более общим, но и более громоздким решением для любых блокирующих задач.