📝 Python

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

P
Автор
Pyland
📅
Опубликовано
30.06.2026
⏱️
Время чтения
1 мин
👁️
Просмотров
102
📊
Уровень
Статья
🐦 💼 ✈️

Иногда нужно вызвать синхронную библиотеку из 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 👁️ 127
📝

pytest-django: тестирование Django

Охватываемые темы: Установка, @pytest.mark.djangodb, Фикстуры, Тестирование views.

📅 30.06.2026 👁️ 134
📝

pip: менеджер пакетов Python

Охватываемые темы: Установка пакетов, Обновление и удаление, requirements.txt, Виртуальное окружение.

📅 30.06.2026 👁️ 120

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

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