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

Асинхронное программирование — это подход, который позволяет выполнять задачи одновременно, не блокируя основной поток выполнения программы. В Python для этого используется модуль asyncio, который предоставляет инструменты для работы с асинхронным кодом.

Основные понятия
  • Синхронный код: Код выполняется последовательно, одна операция за другой.
  • Асинхронный код: Код может приостанавливать выполнение одной задачи и переключаться на другую, что позволяет эффективно использовать ресурсы.
  • Корутина (coroutine): Специальная функция, которая может приостанавливать своё выполнение и возобновлять его позже.
  • Событийный цикл (event loop): Управляет выполнением корутин и переключается между ними.

Ключевые элементы asyncio

Корутины

Корутины — это функции, определённые с помощью ключевого слова async def. Они могут приостанавливать своё выполнение с помощью await.

Пример:
import asyncio async def say_hello(): print("Hello") await asyncio.sleep(1) # Приостановка выполнения на 1 секунду print("World") # Запуск корутины asyncio.run(say_hello())

Ключевое слово await

Ключевое слово await используется для приостановки выполнения корутины до завершения другой корутины или асинхронной операции.

Пример:
import asyncio async def fetch_data(): print("Загрузка данных...") await asyncio.sleep(2) # Имитация загрузки данных print("Данные загружены") return "Данные" async def main(): result = await fetch_data() print("Результат:", result) asyncio.run(main())

Событийный цикл (Event Loop)

Событийный цикл управляет выполнением корутин. Он автоматически создаётся при вызове asyncio.run().

Пример:
import asyncio async def task1(): print("Задача 1 начата") await asyncio.sleep(1) print("Задача 1 завершена") async def task2(): print("Задача 2 начата") await asyncio.sleep(2) print("Задача 2 завершена") async def main(): await asyncio.gather(task1(), task2()) asyncio.run(main())

Основные функции asyncio

asyncio.run()

Запускает корутину и управляет событийным циклом.

Пример:
import asyncio async def my_coroutine(): print("Корутина запущена") asyncio.run(my_coroutine())

asyncio.gather()

Запускает несколько корутин одновременно и ждёт их завершения.

Пример:
import asyncio async def task1(): await asyncio.sleep(1) print("Задача 1 завершена") async def task2(): await asyncio.sleep(2) print("Задача 2 завершена") async def main(): await asyncio.gather(task1(), task2()) asyncio.run(main())

asyncio.create_task()

Создаёт задачу (Task) из корутины, которая выполняется в фоновом режиме.

Пример:
import asyncio async def background_task(): print("Фоновая задача начата") await asyncio.sleep(2) print("Фоновая задача завершена") async def main(): task = asyncio.create_task(background_task()) print("Основная задача продолжает работу") await asyncio.sleep(1) print("Основная задача завершена") await task # Ожидание завершения фоновой задачи asyncio.run(main())

Примеры использования

Пример 1: Асинхронный HTTP-запрос

Использование библиотеки aiohttp для асинхронных HTTP-запросов.

Установим библиотеку aiohttp
pip install aiohttp

import aiohttp import asyncio async def fetch_url(url): async with aiohttp.ClientSession() as session: async with session.get(url) as response: return await response.text() async def main(): url = "https://vozhzhaev.ru" html = await fetch_url(url) print(html[:80]) # Вывод первых 80 символов asyncio.run(main())
Результат:
<!DOCTYPE html>
<html lang="ru">
<head>
    <title>Vozhzhaev.ru</title>

Пример 2: Параллельное выполнение задач
import asyncio async def task(name, delay): print(f"Задача {name} начата") await asyncio.sleep(delay) print(f"Задача {name} завершена") async def main(): await asyncio.gather( task("A", 2), task("B", 1), task("C", 3), ) asyncio.run(main())

Обратите внимание, что все три функции task() запустились одновременно!


Пример 3: Ограничение количества одновременных задач

Использование семафоров для ограничения количества одновременно выполняемых задач.

import asyncio async def worker(semaphore, name): async with semaphore: print(f"Рабочий {name} начал работу") await asyncio.sleep(1) print(f"Рабочий {name} завершил работу") async def main(): semaphore = asyncio.Semaphore(2) # Ограничение на 2 задачи одновременно await asyncio.gather( worker(semaphore, "A"), worker(semaphore, "B"), worker(semaphore, "C"), worker(semaphore, "D"), ) asyncio.run(main())

В этом примере Функции C и D запустятся только тогда, когда выполнятся A и B.


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

  • Используйте асинхронное программирование для задач, связанных с вводом-выводом (I/O-bound), таких как сетевые запросы, работа с файлами и базами данных.

  • Избегайте блокирующих операций (например, time.sleep()), используйте await asyncio.sleep().

  • Для работы с HTTP-запросами используйте библиотеку aiohttp.

  • Для работы с базами данных используйте асинхронные драйверы, такие как asyncpg для PostgreSQL или aiomysql для MySQL.

Асинхронное программирование в Python с использованием asyncio позволяет эффективно выполнять задачи, связанные с вводом-выводом, без блокировки основного потока выполнения. Это особенно полезно для создания высокопроизводительных приложений, таких как веб-серверы, парсеры и системы обработки данных.


Комментарии

Добавить комментарий

Чтобы оставить комменатрий необходимо Авторизоваться