Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

Документы

Медиа

Назад
Вопрос про Python: asyncio, run_in_executor, event loop, blocking code, concurrent futures

Как работает run_in_executor в AsyncIO?

Вопрос проверяет понимание механизма run_in_executor в AsyncIO, который позволяет выполнять блокирующий код в отдельных потоках или процессах, не блокируя основной цикл событий.

Короткий ответ

Метод run_in_executor позволяет запустить блокирующую функцию в отдельном потоке или процессе, пока асинхронный код продолжает работать. Это нужно, чтобы избежать блокировки цикла событий asyncio. Вы передаёте функцию и её аргументы, а метод возвращает awaitable объект, который можно ожидать с await. По умолчанию используется ThreadPoolExecutor, но можно указать и ProcessPoolExecutor.

Длинный ответ

В асинхронном программировании на Python с использованием asyncio основная идея — не блокировать цикл событий (event loop). Однако иногда приходится работать с библиотеками, которые выполняют блокирующие операции (например, тяжёлые вычисления, синхронные вызовы к базам данных или файловые операции). Для таких случаев в asyncio предусмотрен метод run_in_executor.

Как это работает

Метод loop.run_in_executor(executor, func, *args) принимает исполнителя (executor), функцию и её аргументы. Исполнитель — это объект, реализующий интерфейс concurrent.futures.Executor, например ThreadPoolExecutor (по умолчанию) или ProcessPoolExecutor. Метод помещает функцию в очередь исполнителя и возвращает объект asyncio.Future, который можно ожидать с помощью await. Пока функция выполняется в отдельном потоке/процессе, цикл событий продолжает обрабатывать другие задачи.

Пример использования

Допустим, у нас есть синхронная функция, которая имитирует долгую операцию:

import asyncio
import time

def blocking_task(seconds: int) -> str:
    time.sleep(seconds)  # Блокирующий вызов
    return f"Завершено через {seconds} секунд"

async def main():
    loop = asyncio.get_running_loop()
    
    # Запускаем блокирующую функцию в потоковом исполнителе
    future = loop.run_in_executor(None, blocking_task, 2)
    print("Ожидаем результат...")
    result = await future
    print(result)

asyncio.run(main())

Где это применяется

  • Интеграция с синхронными библиотеками (например, для работы с файлами, базами данных).
  • Выполнение CPU-интенсивных задач в процессах (через ProcessPoolExecutor) для избежания влияния GIL.
  • Обработка долгих операций, которые нельзя легко переписать в асинхронном стиле.

Вывод: Используйте run_in_executor, когда вам нужно выполнить блокирующий или ресурсоёмкий код внутри асинхронного приложения, не нарушая работу цикла событий. Это особенно полезно для постепенной миграции с синхронного кода на асинхронный или для работы со сторонними синхронными библиотеками.

Уровень

  • Рейтинг:

    3

  • Сложность:

    5

Навыки

  • Python

    Python

  • Node.js

    Node.js

Ключевые слова

#asyncio

#run_in_executor

#event loop

#blocking code

#concurrent futures

Подпишись на Python Developer в телеграм