← Назад к вопросам

Какая функция в AsyncIO запускает несколько корутин одновременно?

2.0 Middle🔥 211 комментариев
#Python Core#Асинхронность и многопоточность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Какая функция в AsyncIO запускает несколько корутин одновременно?

В Python AsyncIO существует несколько способов запуска множественных корутин, и наиболее распространённые — это asyncio.gather() и asyncio.create_task().

1. asyncio.gather() — основной метод

Это самый практичный и часто используемый способ запуска нескольких корутин:

import asyncio

async def fetch_data(url):
    print(f"Fetching {url}")
    await asyncio.sleep(1)
    return f"Data from {url}"

async def main():
    # Запускаем 3 корутины одновременно
    results = await asyncio.gather(
        fetch_data('http://api1.com'),
        fetch_data('http://api2.com'),
        fetch_data('http://api3.com')
    )
    print(results)
    # Всё выполнится за ~1 секунду, а не за 3!

asyncio.run(main())

Время выполнения: ~1 сек (параллельно), а не 3 сек (последовательно).

2. asyncio.gather() с динамическим списком

Когда количество корутин заранее неизвестно:

import asyncio

async def process_item(item):
    await asyncio.sleep(1)
    return f"Processed: {item}"

async def main():
    items = ['a', 'b', 'c', 'd', 'e']
    
    # Создаём список корутин
    tasks = [process_item(item) for item in items]
    
    # Запускаем все одновременно
    results = await asyncio.gather(*tasks)
    print(results)
    # Выполнится за ~1 сек (все параллельно)

asyncio.run(main())

3. asyncio.create_task() для явного управления

Для большего контроля над задачами:

import asyncio

async def task1():
    await asyncio.sleep(2)
    print("Task 1 done")
    return "Result 1"

async def task2():
    await asyncio.sleep(1)
    print("Task 2 done")
    return "Result 2"

async def main():
    # Создаём задачи явно
    t1 = asyncio.create_task(task1())
    t2 = asyncio.create_task(task2())
    
    # Ждём оба результата
    result1 = await t1
    result2 = await t2
    
    print(result1, result2)
    # Task 2 done (после 1 сек)
    # Task 1 done (после 2 сек)
    # Выполнение: ~2 сек

asyncio.run(main())

4. asyncio.TaskGroup() — современный подход (Python 3.11+)

Новый и более безопасный способ:

import asyncio

async def fetch(url):
    await asyncio.sleep(1)
    return f"Data from {url}"

async def main():
    async with asyncio.TaskGroup() as tg:
        # Все задачи запускаются параллельно
        task1 = tg.create_task(fetch('http://api1.com'))
        task2 = tg.create_task(fetch('http://api2.com'))
        task3 = tg.create_task(fetch('http://api3.com'))
        # Выходим из контекста только когда всё завершится
    
    print(task1.result(), task2.result(), task3.result())
    # Выполнение: ~1 сек

asyncio.run(main())

5. asyncio.as_completed() для обработки по мере готовности

Когда нужна результат сразу, как только корутина завершится:

import asyncio

async def fetch(url, delay):
    await asyncio.sleep(delay)
    return f"Data from {url}"

async def main():
    tasks = [
        fetch('http://api1.com', 3),
        fetch('http://api2.com', 1),
        fetch('http://api3.com', 2),
    ]
    
    # Обрабатываем результаты по мере готовности
    for coro in asyncio.as_completed(tasks):
        result = await coro
        print(f"Got: {result}")  # Выводит в порядке готовности
    
    # api2 готов первым (1с), потом api3 (2с), потом api1 (3с)

asyncio.run(main())

6. asyncio.wait() для детального контроля

Наибольший контроль над ожиданием:

import asyncio

async def task(name, delay):
    await asyncio.sleep(delay)
    return f"{name} done"

async def main():
    tasks = [
        asyncio.create_task(task('Task1', 2)),
        asyncio.create_task(task('Task2', 1)),
        asyncio.create_task(task('Task3', 3)),
    ]
    
    # Ждём первого завершённого
    done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
    print(f"First done: {done.pop().result()}")
    
    # Ждём оставшихся
    done, pending = await asyncio.wait(pending)
    for task in done:
        print(task.result())

asyncio.run(main())

Сравнение методов

# ❌ НЕПРАВИЛЬНО — последовательное выполнение
async def wrong():
    r1 = await fetch('api1')  # 1 сек
    r2 = await fetch('api2')  # 1 сек
    r3 = await fetch('api3')  # 1 сек
    # Всего: 3 сек!

# ✅ ПРАВИЛЬНО — параллельное выполнение
async def correct():
    results = await asyncio.gather(
        fetch('api1'),  # 1 сек (параллельно)
        fetch('api2'),  # 1 сек (параллельно)
        fetch('api3'),  # 1 сек (параллельно)
    )
    # Всего: 1 сек!

Обработка исключений

import asyncio

async def failing_task():
    await asyncio.sleep(0.5)
    raise ValueError("Task failed!")

async def normal_task():
    await asyncio.sleep(1)
    return "Success"

async def main():
    # Игнорировать исключения
    results = await asyncio.gather(
        failing_task(),
        normal_task(),
        return_exceptions=True  # Исключения как результаты
    )
    print(results)  # [ValueError(...), 'Success']

asyncio.run(main())

Практический пример: загрузка множества файлов

import asyncio
import aiohttp

async def download_file(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    urls = [
        'https://api.example.com/data1',
        'https://api.example.com/data2',
        'https://api.example.com/data3',
    ]
    
    async with aiohttp.ClientSession() as session:
        # Загружаем все параллельно
        results = await asyncio.gather(*[
            download_file(session, url) for url in urls
        ])
    
    return results

# Запуск
data = asyncio.run(main())

Рекомендации по выбору

ФункцияКогда использоватьПримечание
gather()Стандартный случайПросто и читаемо
TaskGroup()Python 3.11+Более безопасно
create_task()Нужен контрольЯвное управление
as_completed()Результаты по очередиОбработка как готово
wait()Детальный контрольСложные сценарии

Итоговый ответ

Основная функция — asyncio.gather(), запускает несколько корутин одновременно (конкурентно).

Альтернативы:

  • asyncio.TaskGroup() (Python 3.11+)
  • asyncio.create_task() для явного управления
  • asyncio.as_completed() для обработки по готовности
  • asyncio.wait() для детального контроля

Все они запускают корутины конкурентно (не параллельно), в рамках одного потока на одном ядре процессора.

Какая функция в AsyncIO запускает несколько корутин одновременно? | PrepBro