Справочник Python

Полное руководство по языку на русском

Асинхронное программирование

Основы async/await

import asyncio  # импорт асинхронного модуля

# Асинхронная функция (корутина)
async def greet(name: str) -> str:  # асинхронная функция (корутина)
    await asyncio.sleep(1)  # асинхронная пауза
    return f"Привет, {name}!"  # возврат значения

# Запуск корутины
result = asyncio.run(greet("Мир"))  # запуск асинхронной программы
print(result)  # вывод в консоль

Параллельный запуск

async def fetch_data(url: str) -> str:  # асинхронная функция (корутина)
    print(f"Загрузка {url}")  # вывод в консоль
    await asyncio.sleep(2)  # асинхронная пауза
    return f"Данные {url}"  # возврат значения

async def main():  # асинхронная функция (корутина)
    # Последовательно
    r1 = await fetch_data("url1")  # присваивание
    r2 = await fetch_data("url2")  # присваивание

    # Параллельно
    results = await asyncio.gather(  # параллельный запуск корутин
        fetch_data("url1"),
        fetch_data("url2"),
        fetch_data("url3"),
    )
    print(results)  # вывод в консоль

asyncio.run(main())  # запуск асинхронной программы

asyncio.create_task — фоновые задачи

async def background_work():  # асинхронная функция (корутина)
    while True:  # цикл с предусловием
        print("Работаю...")  # вывод в консоль
        await asyncio.sleep(5)  # асинхронная пауза

async def main():  # асинхронная функция (корутина)
    # Запуск в фоне
    task = asyncio.create_task(background_work())  # создание фоновой задачи
    await asyncio.sleep(12)  # асинхронная пауза
    task.cancel()

asyncio.run(main())  # запуск асинхронной программы

Тайм-ауты

async def slow_operation():  # асинхронная функция (корутина)
    await asyncio.sleep(10)  # асинхронная пауза
    return "Готово"  # возврат значения

async def main():  # асинхронная функция (корутина)
    try:  # начало блока с обработкой исключений
        result = await asyncio.wait_for(slow_operation(), timeout=5)  # ожидание с таймаутом
    except asyncio.TimeoutError:  # обработка исключения
        print("Таймаут! Операция отменена")  # вывод в консоль

asyncio.run(main())  # запуск асинхронной программы

Асинхронные генераторы

async def async_counter(n: int):  # асинхронная функция (корутина)
    for i in range(n):  # цикл по элементам
        await asyncio.sleep(0.5)  # асинхронная пауза
        yield i  # генерация значения

async def main():  # асинхронная функция (корутина)
    async for value in async_counter(5):  # асинхронная итерация
        print(value)  # 0, 1, 2, 3, 4 с интервалом 0.5с

asyncio.run(main())  # запуск асинхронной программы

Работа с сетью (aiohttp)

import aiohttp  # импорт асинхронного HTTP-клиента
import asyncio  # импорт асинхронного модуля

async def fetch(session, url):  # асинхронная функция (корутина)
    async with session.get(url) as response:  # асинхронный контекстный менеджер
        return await response.json()  # возврат значения

async def main():  # асинхронная функция (корутина)
    urls = ["https://api.github.com"] * 5  # инициализация списка
    async with aiohttp.ClientSession() as session:  # асинхронный контекстный менеджер
        tasks = [fetch(session, url) for url in urls]  # списковое включение
        results = await asyncio.gather(*tasks)  # параллельный запуск корутин

asyncio.run(main())  # запуск асинхронной программы

Синхронное vs асинхронное

СинхронноАсинхронно
def func()async def func()
func()await func()
resultawait result
forasync for
withasync with
time.sleep()await asyncio.sleep()

asyncio vs threading vs multiprocessing

# asyncio — для I/O-bound задач (сеть, файлы, БД)
# threading — для I/O-bound, но с GIL
# multiprocessing — для CPU-bound задач (реальные потоки ОС)

import asyncio  # импорт асинхронного модуля
import threading  # импорт модуля
import multiprocessing  # импорт модуля

# asyncio — одна корутина за раз, переключение по await
# threading — переключение по прерыванию ОС
# multiprocessing — параллельное выполнение на всех ядрах

Синхронизация в asyncio

import asyncio  # импорт асинхронного модуля

async def worker(name, lock):  # асинхронная функция (корутина)
    async with lock:  # асинхронный контекстный менеджер
        print(f"{name} работает")  # вывод в консоль
        await asyncio.sleep(1)  # асинхронная пауза

async def main():  # асинхронная функция (корутина)
    lock = asyncio.Lock()  # асинхронный мьютекс
    tasks = [worker(f"W{i}", lock) for i in range(3)]  # последовательность чисел
    await asyncio.gather(*tasks)  # параллельный запуск корутин

asyncio.run(main())  # запуск асинхронной программы