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

Когда применяется асинхронность в Python?

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

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

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

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

Когда применяется асинхронность в Python

Асинхронное программирование — это мощный инструмент для создания высокопроизводительных приложений. Но важно понимать, когда его использовать.

Основы асинхронности

Асинхронное программирование позволяет программе продолжать работу, не ожидая завершения I/O операции:

import asyncio

async def fetch_data(url):
    print(f'Fetching {url}')
    await asyncio.sleep(2)  # Имитируем I/O операцию
    print(f'Finished {url}')

async def main():
    # Запускаем 3 операции одновременно
    await asyncio.gather(
        fetch_data('https://api1.com'),
        fetch_data('https://api2.com'),
        fetch_data('https://api3.com'),
    )
    # Общее время: ~2 сек вместо 6 сек

asyncio.run(main())

Когда использовать асинхронность

1. HTTP запросы и API интеграции

Это самое частое применение асинхронности:

import aiohttp
import asyncio

async def fetch_user_data(user_id):
    async with aiohttp.ClientSession() as session:
        async with session.get(f'https://api.example.com/users/{user_id}') as response:
            return await response.json()

async def main():
    # Получить данные 100 пользователей параллельно
    user_ids = range(1, 101)
    tasks = [fetch_user_data(uid) for uid in user_ids]
    users = await asyncio.gather(*tasks)
    print(f'Получено {len(users)} пользователей')

asyncio.run(main())

Преимущество: 100 запросов занимают ~1-2 сек вместо 100+ сек последовательно.

2. Работа с базами данных

Асинхронные драйверы БД существуют для всех популярных БД:

import asyncpg  # PostgreSQL

async def fetch_users():
    conn = await asyncpg.connect('postgresql://user:pass@localhost/db')
    try:
        # Множество параллельных запросов
        tasks = [
            conn.fetch('SELECT * FROM users WHERE id = $1', i)
            for i in range(1, 101)
        ]
        results = await asyncio.gather(*tasks)
    finally:
        await conn.close()

asyncio.run(fetch_users())

Асинхронные драйверы: asyncpg (PostgreSQL), motor (MongoDB), redis (Redis), tortoise-orm (ORM).

3. WebSocket соединения и реал-тайм данные

import websockets
import asyncio

async def listen_to_stream():
    uri = 'wss://stream.example.com/prices'
    async with websockets.connect(uri) as websocket:
        while True:
            message = await websocket.recv()
            print(f'Price update: {message}')

async def main():
    # Одновременно слушаем несколько потоков
    await asyncio.gather(
        listen_to_stream(),
        process_orders(),
        send_notifications(),
    )

asyncio.run(main())

4. Параллельная обработка множества задач

import aiofiles

async def process_file(filename):
    async with aiofiles.open(filename, 'r') as f:
        content = await f.read()
        # Обработать содержимое
        return len(content)

async def main():
    files = ['file1.txt', 'file2.txt', 'file3.txt']
    sizes = await asyncio.gather(*[process_file(f) for f in files])
    print(f'Общий размер: {sum(sizes)} байт')

asyncio.run(main())

5. Микросервисы и API гейтвеи

from fastapi import FastAPI
import aiohttp

app = FastAPI()

@app.get('/user/{user_id}')
async def get_user(user_id: int):
    # Получить данные из нескольких сервисов параллельно
    async with aiohttp.ClientSession() as session:
        user_task = fetch_from_service(session, f'http://users-service/users/{user_id}')
        orders_task = fetch_from_service(session, f'http://orders-service/orders/{user_id}')
        
        user, orders = await asyncio.gather(user_task, orders_task)
        return {'user': user, 'orders': orders}

6. Долгоживущие серверные приложения

import asyncio

async def main():
    tasks = [
        accept_connections(),  # Принимать новые подключения
        process_queue(),        # Обрабатывать очередь
        monitor_health(),       # Мониторить здоровье
        cleanup_expired(),      # Удалять устаревшие данные
    ]
    await asyncio.gather(*tasks)

asyncio.run(main())

Когда НЕ использовать асинхронность

1. CPU-bound операции

# ❌ ПЛОХО: асинхронность не поможет
async def cpu_intensive():
    count = 0
    for i in range(10**8):
        count += i ** 2
    return count

# ✅ ХОРОШО: используй multiprocessing
import multiprocessing
with multiprocessing.Pool() as pool:
    result = pool.apply_async(cpu_intensive)

Асинхронность помогает при ожидании I/O, а не при вычислениях.

2. Простые синхронные скрипты

# ❌ Излишнее усложнение
async def main():
    async with aiohttp.ClientSession() as session:
        async with session.get('https://api.github.com') as response:
            return await response.json()

# ✅ Просто используй requests
import requests
response = requests.get('https://api.github.com')
data = response.json()

3. Когда библиотеки не асинхронные

# ❌ Блокирует event loop
import time
async def main():
    time.sleep(1)  # Это заблокирует все остальное!

# ✅ Используй asyncio.sleep или потоки
async def main():
    await asyncio.sleep(1)  # Не блокирует

Рекомендации и best practices

1. Профилируй перед оптимизацией

import time
import asyncio

start = time.time()
await main()  # Асинхронная версия
print(f'Async: {time.time() - start:.2f}s')

2. Используй asyncio.gather для параллельных задач

# Правильно
await asyncio.gather(task1, task2, task3)

# Неправильно
await task1
await task2
await task3

3. Обрабатывай исключения

try:
    results = await asyncio.gather(*tasks, return_exceptions=True)
except Exception as e:
    print(f'Ошибка: {e}')

4. Не блокируй event loop

# ❌ Плохо
async def main():
    import time
    time.sleep(1)  # Блокирует!

# ✅ Хорошо
async def main():
    import asyncio
    await asyncio.sleep(1)  # Не блокирует

Выводы

Асинхронность — отличный инструмент для I/O-bound операций. Используй её когда:

  • Много параллельных I/O операций (HTTP, БД, файлы)
  • Нужна высокая пропускная способность
  • Есть асинхронные библиотеки для нужных тебе инструментов
  • Приложение должно обрабатывать много одновременных соединений

Не используй асинхронность для CPU-bound работы — используй multiprocessing вместо этого.