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

Как работает await?

1.8 Middle🔥 231 комментариев
#Асинхронность и многопоточность

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

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

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

Как работает await в Python

Определение

await — это оператор в Python, который приостанавливает выполнение асинхронной функции и ждет результата другой асинхронной функции (корутины). Это позволяет другим корутинам выполняться, пока текущая ждет.

Синтаксис

# Основной синтаксис
async def main():
    result = await some_coroutine()
    return result

# await можно использовать только в async функциях
async def fetch_data():
    response = await asyncio.sleep(1)  # Ждет 1 секунду
    return "data"

# Это ОШИБКА — await вне async функции
def sync_function():
    result = await fetch_data()  # SyntaxError!

Как работает await под капотом

1. Приостановка выполнения

import asyncio

async def task(name, delay):
    print(f"{name} начал")
    await asyncio.sleep(delay)
    print(f"{name} закончил")
    return f"Результат {name}"

async def main():
    # Без await — запускает параллельно
    result1 = await task("Task-1", 2)  # Ждет 2 сек
    result2 = await task("Task-2", 2)  # Ждет еще 2 сек
    # Всего 4 сек

    print(result1)  # Результат Task-1
    print(result2)  # Результат Task-2

asyncio.run(main())

2. Параллельное выполнение с asyncio.gather

import asyncio

async def task(name, delay):
    print(f"{name} начал")
    await asyncio.sleep(delay)
    print(f"{name} закончил")
    return f"Результат {name}"

async def main():
    # Запускает ПАРАЛЛЕЛЬНО
    results = await asyncio.gather(
        task("Task-1", 2),
        task("Task-2", 2),
        task("Task-3", 2)
    )
    # Всего 2 сек (параллельно), не 6 сек
    print(results)

asyncio.run(main())

Практические примеры

HTTP запросы

import aiohttp
import asyncio

async def fetch_url(session, url):
    async with session.get(url) as response:
        return await response.json()

async def fetch_multiple():
    async with aiohttp.ClientSession() as session:
        tasks = [
            fetch_url(session, "https://api.example.com/users/1"),
            fetch_url(session, "https://api.example.com/users/2"),
            fetch_url(session, "https://api.example.com/users/3"),
        ]
        # Выполняет все 3 запроса параллельно
        results = await asyncio.gather(*tasks)
        return results

asyncio.run(fetch_multiple())

FastAPI с await

from fastapi import FastAPI
import asyncio
import httpx

app = FastAPI()

@app.get("/data")
async def get_data():
    # Неправильно — блокирует
    response = requests.get("https://api.example.com/data")
    
    # Правильно — асинхронно
    async with httpx.AsyncClient() as client:
        response = await client.get("https://api.example.com/data")
    
    return response.json()

Database запросы

import asyncpg
import asyncio

async def get_users():
    # Подключение к БД
    conn = await asyncpg.connect(
        "postgresql://user:password@localhost/db"
    )
    
    try:
        # Ждем результата запроса
        users = await conn.fetch('SELECT * FROM users')
        return users
    finally:
        await conn.close()

result = asyncio.run(get_users())

Сравнение синхронного и асинхронного

Синхронный код (блокирующий)

import time
import requests

def sync_fetch():
    start = time.time()
    
    # Блокирует на 1 сек
    response1 = requests.get("https://httpbin.org/delay/1")
    # Блокирует еще на 1 сек
    response2 = requests.get("https://httpbin.org/delay/1")
    # Блокирует еще на 1 сек
    response3 = requests.get("https://httpbin.org/delay/1")
    
    elapsed = time.time() - start
    print(f"Время: {elapsed:.2f}s")  # ~3.0 сек

sync_fetch()

Асинхронный код (неблокирующий)

import asyncio
import httpx
import time

async def async_fetch():
    start = time.time()
    
    async with httpx.AsyncClient() as client:
        tasks = [
            client.get("https://httpbin.org/delay/1"),
            client.get("https://httpbin.org/delay/1"),
            client.get("https://httpbin.org/delay/1"),
        ]
        # Выполняются параллельно
        responses = await asyncio.gather(*tasks)
    
    elapsed = time.time() - start
    print(f"Время: {elapsed:.2f}s")  # ~1.0 сек!

asyncio.run(async_fetch())

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

import asyncio

async def risky_operation():
    await asyncio.sleep(1)
    raise ValueError("Что-то пошло не так")

async def main():
    try:
        result = await risky_operation()
    except ValueError as e:
        print(f"Поймали ошибку: {e}")

asyncio.run(main())

Ключевые моменты

  1. await работает только в async функциях
  2. await приостанавливает текущую корутину, позволяя другим выполняться
  3. asyncio.gather() запускает несколько корутин параллельно
  4. Асинхронный код быстрее для I/O операций (сеть, БД, файлы)
  5. Синхронный код лучше для CPU-bound операций (вычисления)