📝 Python

run_in_executor и anyio: sync-библиотеки в async коде

P
Автор
PyLand Team
📅
Опубликовано
30.06.2026
⏱️
Время чтения
1 мин
👁️
Просмотров
369
🏆
Уровень
Эксперт

Иногда нужно вызвать синхронную библиотеку из async кода не блокируя event loop.

Проблема: блокирующий вызов в async функции

import asyncio, requests

async def bad_fetch(url):
    # ПЛОХО: requests.get блокирует event loop на всё время запроса
    # Все остальные coroutines замерзают и ждут
    return requests.get(url).text

run_in_executor — запуск в пуле потоков

import asyncio
from concurrent.futures import ThreadPoolExecutor
import requests

executor = ThreadPoolExecutor(max_workers=10)

async def fetch_sync(url: str) -> str:
    loop = asyncio.get_running_loop()
    # requests.get выполняется в отдельном потоке, event loop не блокируется
    return await loop.run_in_executor(executor, requests.get, url)

async def main():
    results = await asyncio.gather(
        fetch_sync("https://httpbin.org/get"),
        fetch_sync("https://httpbin.org/post"),
    )

ProcessPoolExecutor — для CPU-bound задач

from concurrent.futures import ProcessPoolExecutor

def heavy_computation(data: list) -> float:
    return sum(x ** 2 for x in data)  # CPU-intensive

async def main():
    loop = asyncio.get_running_loop()
    with ProcessPoolExecutor() as pool:
        result = await loop.run_in_executor(
            pool, heavy_computation, list(range(10_000_000))
        )
    print(result)

anyio — универсальный async backend

anyio работает поверх asyncio или trio — код одинаковый:

import anyio

async def main():
    # to_thread.run_sync — синхронный код в потоке
    result = await anyio.to_thread.run_sync(blocking_function, arg1, arg2)

    # Параллельные задачи через TaskGroup
    async with anyio.create_task_group() as tg:
        tg.start_soon(fetch, url1)
        tg.start_soon(fetch, url2)

# Запуск под asyncio или trio
anyio.run(main)

Когда что использовать

Сценарий Решение
Синхронная I/O библиотека run_in_executor + ThreadPoolExecutor
CPU-intensive задача run_in_executor + ProcessPoolExecutor
Новый async проект httpx, aiosqlite вместо requests, sqlite3
Переносимость между backends anyio

Ваша реакция на статью

💬 Комментарии (0)

🔐 Войдите в систему, чтобы оставить комментарий
🚪 Войти
💭

Комментариев пока нет

Станьте первым, кто поделится мнением об этой статье!

🔗 Похожие

Похожие статьи

Продолжите изучение с этими материалами

📝

Event loop в Python: как asyncio создаёт параллел…

Event loop — сердце asyncio. Он не запускает код параллельно в нескольких потоках. Он переключается...

📅 30.06.2026 👁️ 387
📝

Async context managers: async with и @asynccontex…

Async context managers управляют ресурсами в async коде — соединениями, файлами, транзакциями.

📅 30.06.2026 👁️ 392
📝

asyncio: таймауты, отмена задач и graceful shutdo…

Три вещи которые обязательно нужны в production async коде.

📅 30.06.2026 👁️ 607

Понравилась статья?

Подпишитесь на наши обновления и получайте новые статьи первыми. Развивайтесь вместе с PyLand!