Принципы работы с async/await в Python: практическое руководство с примерами

03.03.25

Разработка - Языки и среды

В статье рассматриваются принципы работы с асинхронным программированием в Python с использованием async/await. На практических примерах показано, как создавать и управлять асинхронными задачами, использовать ключевые методы модуля asyncio, такие как create_task, gather, wait_for, и избегать распространённых ошибок. Материал будет полезен разработчикам, которые хотят улучшить производительность своих приложений за счёт асинхронного выполнения операций.

Асинхронное программирование в Python с использованием async/await позволяет эффективно выполнять задачи, связанные с операциями ввода-вывода (IO), такие как работа с сетью, файлами или базами данных. В этой статье мы рассмотрим основные принципы работы с async/await на практических примерах, а также изучим ключевые методы модуля asyncio.

Рассмотрим принципы работы с async/await на практических примерах. Для начала рассмотрим базовый пример асинхронной функции, которая имитирует загрузку данных с разных URL:

 
 простой пример асинхронного кода
import asyncio

async def fetch_data(url):
    await asyncio.sleep(1)
    return f"Данные с {url}"

async def main():
    # Параллельное создание задач
    task1 = asyncio.create_task(fetch_data("site1.com"))
    task2 = asyncio.create_task(fetch_data("site2.com"))
    
    # Ждём результатов обоих задач одновременно
    result1, result2 = await asyncio.gather(task1, task2)
    
    print(result1)
    print(result2)

# Запуск
# asyncio.run(main())

 

 Теперь рассмотрим

 
 параллельное выполнение асинхронных операций

Для лучшего понимания потока выполнения асинхронного кода, рассмотрим рисунок последовательности: 

import asyncio

async def fetch_data(url):
    await asyncio.sleep(1)
    return f"Данные с {url}"

async def main():
    # Параллельное создание задач
    task1 = asyncio.create_task(fetch_data("site1.com"))
    task2 = asyncio.create_task(fetch_data("site2.com"))
    
    # Ждём результатов обоих задач одновременно
    result1, result2 = await asyncio.gather(task1, task2)
    
    print(result1)
    print(result2)

# Запуск
# asyncio.run(main())

Рассмотрим подробнее, что происходит:

1. Создание задачи

Главная программа создаёт две задачи одновременно, не дожидаясь завершения первой

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

Обе задачи выполняются независимо друг от друга, каждая ожидает по 1 секунде

3. Обработка результата

После завершения обеих задач их результаты собираются через asyncio.gather()

Для лучшего понимания преимуществ async/await, сравним синхронный и асинхронный подходы:

 

Характеристика Синхронный код Асинхронный код (async/await)
Выполнение операций Последовательное, блокирующее Параллельное, неблокирующее
Использование CPU
Ожидание операции занимает ресурсы
Время ожидания используется для других задач
Сложность кода Простой, линейный Немного сложнее, но читаемый
Масштабируемость Ограниченная Высокая при работе с IO операциями

 

Основные преимущества async/await:

  1. Эффективность:
    • Одновременное выполнение нескольких операций
    • Оптимальное использование системных ресурсов
    • Быстрое выполнение IO-операций
  2. Читаемость кода:
    • Синтаксис близок к обычному синхронному коду
    • Логика выполнения более очевидна
    • Проще поддерживать и модифицировать
  3. Масштабируемость:
    • Легко добавлять новые асинхронные операции
    • Удобно управлять параллельным выполнением
    • Простая обработка ошибок через try-except

Для практического применения важно помнить:

  • Используйте async/await для IO-операций (сеть, файлы, базы данных)
  • Комбинируйте задачи с помощью asyncio.gather() для параллельного выполнения
  • Обрабатывайте ошибки в каждой асинхронной функции отдельно
  • Не используйте async/await для вычислительных задач без IO операций

Такой подход позволяет создавать эффективные и масштабируемые приложения с минимальными изменениями в структуре кода.

Давайте рассмотрим основные полезные процедуры модуля asyncio и их практическое применение.

 

Основные методы управления задачами

 
 1. create_task() - создание независимых задач
 
 2. gather() - параллельное выполнение задач
 
3. wait_for() - выполнение с таймаутом
 
 4. wait() - ожидание нескольких задач
 
 5. Queue - асинхронная очередь
 
 6. Semaphore - ограничение параллельных операций
 
 7. Структура асинхронного приложения
 
 8. Управление задачами
 
 9. Работа с ресурсами
 
 10. Обработка ошибок

Рекомендации по использованию

  1. Логирование:
    • Всегда используйте именованные логгеры
    • Логируйте ошибки с контекстом
    • Используйте разные уровни логирования (INFO, WARNING, ERROR)
  2. Управление ресурсами:
    • Используйте контекстные менеджеры (async with)
    • Всегда очищайте ресурсы в блоке finally
    • Используйте семафоры для ограничения параллельных операций
  3. Обработка ошибок:
    • Обрабатывайте специфические исключения
    • Используйте return_exceptions в gather
    • Логируйте ошибки с контекстом
  4. Таймауты:
    • Устанавливайте разумные таймауты для операций
    • Обрабатывайте TimeoutError
    • Отменяйте задачи при таймауте
  5. Именование задач:
    • Давайте осмысленные имена задачам
    • Используйте name параметр в create_task
    • Это помогает в отладке и мониторинге

Анти-паттерны, которых следует избегать

 
 1. Небезопасное создание зада
 
 2. Неправильная обработка ошибок
 
 3. Нарушение иерархии ресурсов

 

Заключение

Асинхронное программирование с использованием async/await позволяет создавать высокопроизводительные и масштабируемые приложения. Правильное использование методов модуля asyncio и соблюдение рекомендаций помогут избежать распространённых ошибок и улучшить качество кода.

Эта статья поможет вам освоить асинхронное программирование в Python и эффективно применять его в своих проектах.

async/await asyncio асинхронное программирование Python create_task gather wait_for семафоры асинхронные очереди обработка ошибок таймауты масштабируемость IO-операции.

См. также

Языки и среды Программист Платформа 1С v8.3 Бесплатно (free)

Будем писать свои скрипты на питоне и запускать их на 1С.

15.04.2024    5564    YA_418728146    14    

62

Мобильная разработка Языки и среды 1С:Элемент Программист Бесплатно (free)

Flutter может быть использован с 1С:Предприятием для разработки кроссплатформенных мобильных приложений, обеспечивая единый интерфейс и функциональность на устройствах под управлением iOS и Android. Это позволяет создавать приложения с высокой производительностью благодаря использованию собственного движка рендеринга Flutter. Интеграция Flutter с 1С:Предприятием позволяет создавать мобильные приложения любого уровня сложности, интегрировать их в корпоративные информационные системы, а также реализовывать бизнес-логику

19.03.2024    23757    ROk_dev    81    

45

Языки и среды Программист Стажер Платформа 1С v8.3 Бесплатно (free)

Существует множество языков программирования, и каждый имеет свои особенности по работе с типами данных. Слабые, явные, динамические и другие... Но кто же здесь 1С и почему с приходом "строгой" типизации EDT 1С-программистам стоит задуматься над изменением своих привычек.

16.01.2024    8959    SeiOkami    25    

62

Языки и среды Программист Бесплатно (free)

Пример небольшого приложения, с которого можно начать изучать язык программирования Dart.

08.08.2023    4755    acvatoris    6    

15

Языки и среды Программист Платформа 1С v8.3 Россия Бесплатно (free)

Написание статического анализатора для 1С традиционным способом на Си.

30.06.2023    3825    prohorp    15    

12

Языки и среды Программист Абонемент ($m)

Поставили нам задачу - вынести на отдельный сервер функционал получения заказов от клиентов по электронной почте, парсинг полученных XLS в приемлемый вид и трансформация заказов в красивый JSON, понятный нашей учетной системе на 1С. Всю эту красоту желательно запустить в отдельном докер - контейнере, по возможности не тратя лицензии, поэтому отдельно стоящую конфигурацию на БСП отвергаем сразу. Можно было бы собрать всё на Apache Airflow или Apache NiFi, но решили попробовать реализовать всю логику без Open Source, будем делать свой ETL, с Исполнителем, который в версии 3.0 научился взаимодействовать с электронной почтой по IMAP. Начнем с середины - сначала напишем скрипты, а потом соберем их в рабочую конструкцию

1 стартмани

01.06.2023    2544    0    kembrik    2    

7

Языки и среды Инструментарий разработчика Программист Платформа 1С v8.3 1C:Бухгалтерия Абонемент ($m)

Вставки кода на C# внутри кода на 1С.

7 стартмани

07.04.2023    11119    4    SerVer1C    58    

45

Языки и среды Программист Платформа 1С v8.3 Бесплатно (free)

При работе с 1С ORM (object relation mapping) все время преследует ощущение постоянного создания монолитного приложения — один раз привязался к какой либо сущности (например, справочник Контрагенты), и весь код заполнен ссылками на эту конкретную реализацию. Можно ли независимо разрабатывать в ORM совместимые между собой справочник «Контрагентов» и использующий его документ «Платежное поручение», но при этом избежать жестких зависимостей? Спасут ли нас микросервисы? Пример на аннотациях Java демонстрирует, как это возможно делать.

13.03.2023    1496    1CUnlimited    0    

3
Оставьте свое сообщение