Понимание и использование ключевых слов asyncio, async/await для создания высокопроизводительных и масштабируемых приложений
Асинхронное программирование — это парадигма программирования, которая позволяет выполнять несколько задач одновременно, не блокируя выполнение основного потока. Это особенно важно для веб-разработки и работы с сетями, где приложения часто ожидают ответов от внешних ресурсов.
Современные веб-приложения должны обрабатывать тысячи одновременных подключений. Традиционные синхронные подходы создают отдельный поток или процесс для каждого подключения, что потребляет много ресурсов. Асинхронный код позволяет обрабатывать множество операций ввода-вывода в одном потоке.
Асинхронные приложения могут обрабатывать тысячи одновременных соединений с минимальными ресурсами.
Легко масштабируются для обработки растущего количества пользователей и запросов.
Оптимально для операций ввода-вывода: сетевые запросы, чтение/запись файлов, работа с базами данных.
async Объявляет асинхронную функцию
await Приостанавливает выполнение функции до завершения awaitable объекта
asyncio Библиотека Python для написания параллельного кода с использованием синтаксиса async/await
Event Loop Цикл событий, который планирует и выполняет асинхронные задачи
Ключевые слова async и await появились в Python 3.5 и стали стандартным способом написания асинхронного кода.
import time
def fetch_data():
time.sleep(2) # Блокирующая операция
return "Данные"
start = time.time()
result1 = fetch_data()
result2 = fetch_data()
result3 = fetch_data()
end = time.time()
print(f"Результат: {result1}, {result2}, {result3}")
print(f"Время выполнения: {end-start:.2f} секунд")
# Время выполнения: ~6 секунд
import asyncio
import time
async def fetch_data():
await asyncio.sleep(2) # Неблокирующая операция
return "Данные"
async def main():
start = time.time()
# Запускаем все задачи одновременно
task1 = asyncio.create_task(fetch_data())
task2 = asyncio.create_task(fetch_data())
task3 = asyncio.create_task(fetch_data())
result1 = await task1
result2 = await task2
result3 = await task3
end = time.time()
print(f"Результат: {result1}, {result2}, {result3}")
print(f"Время выполнения: {end-start:.2f} секунд")
# Время выполнения: ~2 секунды
asyncio.run(main())
async defawait для вызова других асинхронных функцийasyncio.run()asyncio.create_task() для параллельного выполненияawait вне асинхронной функцииМодуль asyncio предоставляет инфраструктуру для написания однопоточного параллельного кода с использованием корутин, multiplexing I/O доступа через сокеты и другие ресурсы, запуска сетевых клиентов и серверов и т.д.
import asyncio
# 1. Event Loop - цикл событий
loop = asyncio.get_event_loop()
# 2. Coroutine - корутина (асинхронная функция)
async def my_coroutine():
await asyncio.sleep(1)
return "Готово"
# 3. Task - задача, которая запускает корутину
task = loop.create_task(my_coroutine())
# 4. Future - объект, представляющий результат асинхронной операции
future = asyncio.Future()
# 5. Запуск event loop
async def main():
result = await my_coroutine()
print(result)
# Современный способ запуска (Python 3.7+)
asyncio.run(main())
Нажмите кнопку, чтобы запустить демонстрацию параллельного выполнения задач
Здесь будут отображаться результаты выполнения асинхронных задач...
asyncio.gather() - запускает несколько awaitable объектов одновременно и собирает результаты
asyncio.wait() - ожидает завершения нескольких задач с возможностью таймаута
asyncio.sleep() - неблокирующая задержка выполнения
asyncio.create_task() - создает задачу для выполнения корутины
asyncio.run() - запускает асинхронную функцию (Python 3.7+)
import asyncio
import aiohttp
import time
async def fetch_url(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
urls = [
'https://httpbin.org/delay/1',
'https://httpbin.org/delay/2',
'https://httpbin.org/delay/1',
'https://httpbin.org/delay/3',
]
start_time = time.time()
async with aiohttp.ClientSession() as session:
tasks = [fetch_url(session, url) for url in urls]
results = await asyncio.gather(*tasks)
end_time = time.time()
print(f"Получено {len(results)} страниц")
print(f"Общее время: {end_time - start_time:.2f} секунд")
# Все URL будут загружены параллельно, общее время ~3 секунды
asyncio.run(main())
import asyncio
import websockets
async def echo_server(websocket, path):
async for message in websocket:
print(f"Получено сообщение: {message}")
await websocket.send(f"Эхо: {message}")
async def main():
server = await websockets.serve(echo_server, "localhost", 8765)
print("Сервер запущен на ws://localhost:8765")
await server.wait_closed()
# Запуск сервера
# asyncio.run(main())
import asyncio
import random
async def producer(queue, id):
for i in range(3):
item = f"Элемент {i} от производителя {id}"
await queue.put(item)
print(f"Производитель {id} добавил: {item}")
await asyncio.sleep(random.uniform(0.1, 0.5))
async def consumer(queue, id):
while True:
item = await queue.get()
if item is None:
break
print(f"Потребитель {id} обработал: {item}")
await asyncio.sleep(random.uniform(0.2, 0.7))
queue.task_done()
async def main():
queue = asyncio.Queue()
producers = [asyncio.create_task(producer(queue, i)) for i in range(2)]
consumers = [asyncio.create_task(consumer(queue, i)) for i in range(3)]
await asyncio.gather(*producers)
await queue.join()
for _ in range(3):
await queue.put(None)
await asyncio.gather(*consumers)
asyncio.run(main())
| Критерий | Синхронный подход | Асинхронный подход |
|---|---|---|
| Модель выполнения | Блокирующая, пошаговая | Неблокирующая, на основе событий |
| Производительность I/O операций | Низкая (одна операция за раз) | Высокая (множество операций параллельно) |
| Использование ресурсов | Высокое (много потоков/процессов) | Низкое (один поток) |
| Сложность кода | Проще для понимания | Сложнее, требует понимания асинхронности |
| Лучший случай использования | CPU-интенсивные задачи | I/O-интенсивные задачи |
| Библиотеки Python | Requests, synchronous SQL drivers | aiohttp, aiomysql, asyncpg |
Используйте асинхронность когда:
Избегайте асинхронности когда:
FastAPI Современный веб-фреймворк для создания API с автоматической документацией
Sanic Асинхронный веб-фреймворк, вдохновленный Flask
Quart Асинхронная версия Flask
Tornado Асинхронный веб-фреймворк и библиотека сетевого программирования
aiohttp Асинхронный HTTP клиент/сервер
asyncio.run() для запуска асинхронного кодаasyncio.get_event_loop().set_debug(True)