Зачем нужна асинхронность python
Перейти к содержимому

Зачем нужна асинхронность python

  • автор:

Зачем нужна асинхронность

Бекенд-разработчики обычно пишут синхронный код. В нём команды исполняются одна за другой:

# . grand_total = sum(cart_products.values()) print(grand_total) # . 

Ничего не требуется предпринимать, если синхронный код работает быстро. Проблемы возникают, когда он подвисает и не реагирует на команды пользователя. Синхронный email-клиент не сможет реагировать на нажатие кнопок, пока он скачивает почту. А скачивание тоже происходит синхронно: пока не ответит первый email-провайдер, клиент не отправит запрос второму.

Асинхронное программирование позволяет сделать несколько быстрых действий, пока не завершится долгое. Email-клиент может показывать пользователю скачанные письма, пока новая почта асинхронно загружается. Вот как это выглядит в псевдокоде:

while True: download_progress = download_emails_step_by_step(download_progress) click = read_click() # . 

Асинхронным этот код делает функция, которая названа download_emails_step_by_step . Она скачивает не всю почту за раз, а понемногу. Скачав кусочек, она возвращает управление циклу while True . Этот цикл дальше запустит read_click , которая вернёт клик пользователя, если он был, и None , если не было. Другие функции в этом цикле аналогичные: они делают небольшое действие, останавливаются, возвращают управление циклу, который их снова запускает позже.

Обычные функции в Питоне работают не так, как это принято в асинхронном программировании. Функция input , например, ждёт пользовательского ввода и может долго не возвращать управление вызвавшему её коду. Поэтому в язык добавили библиотеку asyncio, которая содержит инструменты для работы с асинхронным кодом и асинхронные эквиваленты синхронных функций (например, sleep).

Привычные инструменты ломают асинхронный код

Рассмотрим ещё один пример. Есть сервер, который возвращает координаты перемещения автобусов в реальном времени. Для каждого автобуса ведётся трансляция его координат. Асинхронный код поможет отрисовать маршрут движения автобуса до того, как закончится трансляция координат. Нам не обязательно даже знать, закончится ли она, потому что данные обрабатываются по частям, небольшими порциями.

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

Если потоков данных много, то спасет асинхронность

Попробуйте бесплатные уроки по Python

Получите крутое код-ревью от практикующих программистов с разбором ошибок и рекомендациями, на что обратить внимание — бесплатно.

Переходите на страницу учебных модулей «Девмана» и выбирайте тему.

Особенности асинхронности в Python

Привет, Хабр! Меня зовут Николай Нагорный, я работаю в Росбанке над платформой Advisors’ Axiom. В этом посте я подробно расскажу о важной фиче, которая появилась в Python 3.5 — асинхронности. Затрону основные концепции и инструменты, приведу примеры кода. Пост будет полезен новичкам для понимания основ асинхронности и, может, даже опытным разработчикам в поиске новых идей и подходов.

Начнем с определения. Асинхронность — это парадигма программирования, которая позволяет выполнять несколько задач одновременно, не дожидаясь завершения каждой из них; важный инструмент для решения проблем с производительностью в веб-приложениях и серверных технологиях. С момента появления асинхронности в Python сразу было доступно несколько способов реализации асинхронного кода. Чаще всего для асинхронных операций в Python используют библиотеки async/await и asyncio. Также асинхронность может быть использована для веб-приложений в сочетании с фреймворками, например с Django, Flask или Fast API.

Асинхронность в чистом Python

Один из способов реализации асинхронности в Python — декоратор @asyncio.coroutine. Вот функция-корутина, которая выполняет ожидание в течение некоторого времени:

import asyncio # импорт библиотеки @asyncio.coroutine # декоратор def my_coroutine(seconds): print ('Starting coroutine') yield from asyncio.sleep(seconds) # возвращаем результат print ('Finishing coroutine') loop = asyncio.get_event_loop () # создаем объект loop.run_until_complete(my_coroutine (2)) # запускаем loop.close () # закрываем

Другой, более предпочтительный способ появился в языке позднее — это асинхронные функции (Async Functions), которые вызываются через async. В примере ниже функция my_coroutine задана асинхронно, то есть программа не будет ждать завершения ее работы, а продолжит выполнение следующих команд:

import asyncio # импортируем библиотеку async def my_async_function (seconds) : # создаем асинхронную функцию print ('Starting async function') await asyncio.sleep (seconds) # вызываем метод await для ожидания print ('Finishing async function') loop = asyncio.get_event_loop () # создаем объект loop.run_until_complete(my_async_function (2)) # запускаем loop.close () # закрываем

Кроме того, в Python можно создавать асинхронные контексты с помощью ключевого слова async with. Это позволяет выполнять асинхронные операции внутри контекста, например открытие и закрытие файла:

import asyncio # импортируем библиотеку async def read_file (filename): # создаем асинхронную функцию async with open(filename, 'r') as f: # открываем файл на чтение contents = await f. read () # читаем весь файл print (contents)

Модуль asyncio с методами async functions, async with, контексты и корутины — выбор средств асинхронности в Python неплохой. Комбинируя их, можно создавать программы с высокой параллельностью и улучшать их производительность, а также избегать блокировок программы во время длительных операций. Помните, что асинхронный код сам по себе более сложен для понимания и реализации, поэтому используйте его с умом. И тогда перечисленные инструменты раскроют весь свой немаленький потенциал.

Асинхронность во фреймворках Python — Django, FastAPI, Flask

Теперь поговорим об использовании асинхронности с популярными фреймворками — Django, Flask и FastAPI. Ни один из них не имеет встроенной поддержки асинхронности, но ее можно добавить с помощью внешних библиотек.

Для реализации асинхронных вызовов FastAPI использует стандартный модуль asyncio и поддерживает асинхронные функции нативно, на уровне ядра. У Django и Flask такой поддержки нет, но они тоже умеют работать с асинхронными библиотеками asyncio или aiohttp. Так что разогнать свои веб-приложения с помощью асинхронности использование этих фреймворков не помешает. Вот пример реализации с библиотекой aiohttp в Flask:

import aiohttp # импортируем библиотеку для работы с асинхронным примером from flask import Flask # импортируем библиотеку для работы с фреймворком app = Flask(__name__) # создаем приложение @app.route("/") # объявляем страницу async def main(): # создаем асинхронную функцию async with aiohttp.ClientSession() as session: # открываем асинхронную клиентскую сессию async with session.get ("https://www.example.com") as response: # используя сессию делаем асинхронный запрос return response.text if __name__ == Il “__main__”: # объявляем секцию main app.run() # запускаем фреймворк по с настройками по умолчанию

Асинхронность в веб-приложениях лучше всего раскрывается при работе с длительными операциями или вызовами API. Но учтите, что так вы подписываетесь на более сложную отладку и поддержку.

Вот еще пример асинхронных функций в FastAPI: функция main использует asyncio.sleep для задержки выполнения на 10 секунд. Это может пригодиться, например, для ожидания ответа от внешнего API:

from fastapi import FastAPI # импортируем библиотеку для работы с фреймворком Aimport asyncio # импортируем библиотеку для работы с асинхронным примером app = FastAPI() # создаем приложение @app.get("/") # объявляем страницу async def main(): #создаем асинхронную функцию await asyncio.sleep(10) # с помощью асинхронной библиотеки запускаем наш пример return if __name__ == "__main__": # объявляем секцию main uvicorn.run (app) # запускаем фреймворк по с настройками по умолчанию

Что касается Django, то он также поддерживает асинхронное программирование с помощью внешних библиотек Django Channels.

from channels.generic.websocket import AsyncWebsocketConsumer #библиотека для работы с асинхронностью §class MyConsumer (AsyncWebsocketConsumer): async def connect(self): # создаем асинхронный метод await self.accept() # ожидаем await asyncio.sleep (10) # выполняем действия await self.send(text_data="Hello World") # отправляем данные await self.close() # закрываем

В этом примере класс MyConsumer реализует асинхронное вебсокет-соединение через метод connect. Метод accept принимает соединение, а метод send отправляет сообщение клиенту. Для задержки отправки сообщения на 10 секунд используется функция asyncio.sleep. И в конце метод close закрывает соединение.

С помощью асинхронного программирования вы можете использовать все доступные ресурсы для обработки множества запросов одновременно, а не ставить их в очередь. Создаются асинхронные вьюхи в каждом фреймворке по-своему. В Django вы можете использовать декоратор async из библиотеки asyncio. Для Flask — декоратор asyncio.coroutine; Flask использует библиотеку gevent для управления асинхронными задачами. FastAPI имеет встроенную поддержку асинхронных функций, поэтому там можно использовать async def. Выбирайте фреймворк для работы с асинхронностью исходя из собственных задач и предпочтений. Я привел варианты выше, поскольку они точно предлагают удобный инструментарий для управления асинхронными задачами.

ORM — Object-Relational Mapping

ORM (Object-Relational Mapping) — это технология, которая позволяет связаться с базой данных, используя объекты Python, вместо того чтобы писать сырые SQL-запросы. Многие ORM для Python, такие как SQLAlchemy и Django ORM, поддерживают асинхронные версии. Библиотеки asyncio или asyncpg позволяют использовать асинхронные версии этих ORM в асинхронных приложениях.

С помощью ORM вы можете выполнять запросы к базе данных асинхронно, вместо того чтобы ждать ответа перед выполнением следующей задачи. Так вы можете увеличить производительность приложения и оптимизировать использование ресурсов. Пример асинхронного подключения к СУБД:

import asyncio # библиотека для работы с асинхронным кодом import asyncpg # библиотека для подключения к субд async def main(): ## создаем асинхронную функцию conn = await asyncpg.connect (user='user', password='password', database='database', host='host') # подключаем к субд # создание таблицы await conn.execute(''' CREATE TABLE IF NOT EXISTS test_table ( id serial PRIMARY KEY, name text NOT NULL ) ''') # вставка данных в таблицу await conn.execute('" INSERT INTO test_table (name) VALUES ($1) ''', 'John Doe') # выборка данных из таблицы result = await conn.fetch(''' SELECT * FROM test_table ''') print (result) # показываем результат await conn.close() # закрываем соединение asyncio.run(main())

В этом примере происходит соединение с базой данных, далее создание таблицы, вставка данных в таблицу и выборка данных. Все эти операции выполняются асинхронно, так что вы можете выполнять другие задачи одновременно с запросом к базе данных. Обработка запросов ускоряется и пользовательский опыт улучшается, так как во время ожидания ответа от базы данных приложение не проседает. Но еще раз напомню, что асинхронный код более сложен в реализации и отладке, поэтому оценивайте свои возможности и потребности проекта.

В нашей троице Django, Flask и FastAPI асинхронность в работе с базой данных можно реализовать через библиотеки asyncio и aiomysql. Они представляют собой асинхронные версии стандартных модулей для работы с базами данных, psycopg2 и mysql-python. Например в Django можно использовать asyncpg для работы PostgreSQL в асинхронном режиме. Соответственно, в Flask и FastAPI можно использовать aiomysql для MySQL.

Асинхронные ORM, такие как asyncio-orm или Tortoise-ORM, могут улучшить и производительность работы с базой данных в асинхронном режиме. В большинстве случаев асинхронный код позволяет использовать базу данных более эффективно за счет минимизации ожидания выполнения запросов. Покажу, как асинхронность может улучшить работу с базой данных, на примере с asyncio и aiomysql:

pip install aiomysql import asyncio # библиотека для работы с асинхронным кодом import aiomysql # библиотека для подключения к субд async def main(): # создаем асинхронную функцию conn = await aiomysql.connect(host='localhost', user='user', password='password', db='dbname', charset='utf8mb4') # подключаем к субд async with conn.cursor() as cursor: # открываем подключение await cursor.execute ("SELECT * FROM table") # добавляем запрос result = await cursor.fetchall() # получаем все из таблицы print(result) # показываем запрос asyncio.run(main ())

Здесь мы создали простое приложение, которое подключается к базе данных и выполняет запрос. Используется асинхронный контекст-менеджер для управления соединением с базой данных, а затем выполняется SELECT-запрос и вывод результата.

Использование асинхронности в ORM может повысить производительность приложения, поскольку запросы к базе данных при этом выполняются в фоновом режиме, без блокировки потоков исполнения. Но помните о неминуемом усложнении кода и отладки. Django ORM и некоторые другие ORM поддерживают асинхронные запросы. Запросы эти не встроены в фундаментальный дизайн фреймворка и могут требовать дополнительных инструментов и настроек. С этой точки зрения проще использовать Flask с его asyncio.

Ограничения асинхронности

Не все базы данных поддерживают асинхронный режим работы — например реляционные базы данных, такие как PostgreSQL и MySQL. При использовании таких баз данных с асинхронным кодом вам могут потребоваться специальные библиотеки типа asyncpg.

Еще одно ограничение возникает при работе с транзакциями. Они обычно выполняются в блокирующем режиме, который заставляет все остальные запросы ждать, пока транзакция не будет завершена. Это может стать проблемой в асинхронных приложениях, так как они ожидают ответа в неблокирующем режиме. Здесь есть несколько решений: использование асинхронных ORM (asyncpg) или использование блокировок на уровне базы данных. Однако так вы будете вынуждены потерять в производительности и писать более сложный код.

Все три фреймворка, что мы рассматривали выше — FastAPI, Django и Flask — используют ORM (Object Relational Mapping) для управления базами данных. В ORM для работы с базами данных предусмотрены простые CRUD-операции (Create, Read, Update, Delete). В FastAPI и Flask ORM реализуют через сторонние библиотеки, такие как SQLAlchemy и Flask-SQLAlchemy. После этого с базами данных можно использовать и синхронные, и асинхронные операции (async for, async with, async/await). Django же с версии 3.0 поддерживает асинхронные операции с базой данных нативно, и вам тоже не придется ждать.

Заключение

Сегодня асинхронность очень важна для решения проблем с производительностью в веб-приложениях. В Python асинхронные функции можно организовать с помощью модуля asyncio. В фреймворках Django, Flask и FastAPI можно использовать асинхронные возможности для оптимизации работы с базами данных и выполнения сложных операций.

Следует помнить, что асинхронный стиль программирования усложнит код и отладку. И, конечно, потребует довольно глубокого понимания асинхронных принципов. Так что решение об использовании асинхронности должно быть осознанным и основываться на конкретных задачах.

Несмотря на это, асинхронность остается важным инструментом для улучшения производительности веб-приложений.

Асинхронный Python: различные формы конкурентности

Асинхронный Python: различные формы конкурентности

Это перевод статьи Абу Ашраф Маснуна «Async Python: The Different Forms of Concurrency».

С появлением Python 3 довольно много шума об «асинхронности» и «параллелизме», можно полагать, что Python недавно представил эти возможности/концепции. Но это не так. Мы много раз использовали эти операции. Кроме того, новички могут подумать, что asyncio является единственным или лучшим способом воссоздать и использовать асинхронные/параллельные операции. В этой статье мы рассмотрим различные способы достижения параллелизма, их преимущества и недостатки.

Определение терминов:

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

Синхронный и асинхронный:

В ​синхронных операциях задачи выполняются друг за другом. В асинхронных — задачи могут запускаться и завершаться независимо друг от друга. Одна асинхронная задача может запускаться и продолжать выполняться, пока выполнение переходит к новой задаче. Асинхронные задачи ​не блокируют (не заставляют ждать завершения выполнения задачи) операции и обычно выполняются в фоновом режиме.

Например, вы должны обратиться в туристическое агентство, чтобы спланировать свой следующий отпуск. Вам нужно отправить письмо своему руководителю, прежде чем улететь. В синхронном режиме, вы сначала позвоните в туристическое агентство, и если вас попросят подождать, то вы будете ждать, пока вам не ответят. Затем вы начнёте писать письмо руководителю. Таким образом, вы выполняете задачи последовательно, одна за другой.

Но, если вы умны, то пока вас попросили подождать, вы начнёте писать письмо, и когда с вами снова заговорят, вы приостановите написание, поговорите, а затем допишете письмо. Вы также можете попросить друга позвонить в агентство, а сами написать письмо. Это асинхронность, задачи не блокируют друг друга.

Конкурентность и параллелизм:

Конкурентность подразумевает, что две задачи выполняются совместно. В нашем предыдущем примере, когда мы рассматривали асинхронный пример, мы постепенно продвигались то в написании письма, то в разговоре с турагентством. Это ​конкурентность.

Когда мы попросили позвонить друга, а сами писали письмо, то задачи выполнялись ​параллельно.​

Параллелизм по сути является формой конкурентности. Но параллелизм зависит от оборудования. Например, если в CPU только одно ядро, то две задачи не могут выполняться параллельно. Они просто делят процессорное время между собой. Тогда это конкурентность, но не параллелизм. Но когда у нас есть несколько ядер, мы можем выполнять несколько операций (в зависимости от количества ядер) одновременно.

  • Синхронность: блокирует операции (блокирующие)
  • Асинхронность: не блокирует операции (неблокирующие)
  • Конкурентность: совместный прогресс (совместные)
  • Параллелизм: параллельный прогресс (параллельные)

Параллелизм подразумевает конкурентность. Но конкурентность не всегда подразумевает параллелизм.

Потоки и процессы

Python поддерживает потоки уже очень давно. Потоки позволяют выполнять операции конкурентно. Но есть проблема, связанная с Global Interpreter Lock (GIL) из-за которой потоки не могли обеспечить настоящий параллелизм. И тем не менее, с появлением multiprocessing можно использовать несколько ядер с помощью Python.

Потоки (Threads)

Рассмотрим небольшой пример. В нижеследующем коде функция worker будет выполняться в нескольких потоках асинхронно и одновременно.

import threading import time import random def worker(number): sleep = random.randrange(1, 10) time.sleep(sleep) print("I am Worker <>, I slept for <> seconds".format(number, sleep)) for i in range(5): t = threading.Thread(target=worker, args=(i,)) t.start() print("All Threads are queued, let's see when they finish!")

А вот пример выходных данных:

$ python thread_test.py All Threads are queued, let's see when they finish! I am Worker 1, I slept for 1 seconds I am Worker 3, I slept for 4 seconds I am Worker 4, I slept for 5 seconds I am Worker 2, I slept for 7 seconds I am Worker 0, I slept for 9 seconds

Таким образом мы запустили 5 потоков для совместной работы, и после их старта (т.е. после запуска функции worker) операция не ждёт завершения работы потоков прежде чем перейти к следующему оператору print. Это асинхронная операция.

В нашем примере мы передали функцию в конструктор Thread. Если бы мы хотели, то могли бы реализовать подкласс с методом (ООП стиль).

Global Interpreter Lock (GIL)

GIL нужен, чтобы сделать обработку памяти CPython проще и обеспечить наилучшую интеграцию с C.

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

Краткие сведения о GIL:

  • Одновременно может выполняться один поток.
  • Интерпретатор Python переключается между потоками для достижения конкурентности.
  • GIL применим к CPython (стандартной реализации). Но, например, Jython и IronPython не имеют GIL.
  • GIL делает однопоточные программы быстрыми.
  • Операциям ввода/вывода GIL обычно не мешает.
  • GIL позволяет легко интегрировать непотокобезопасные библиотеки на C, благодаря GIL у нас есть много высокопроизводительных расширений/модулей, написанных на C.
  • Для CPU-зависимых задач интерпретатор делает проверку каждые N тиков и переключает потоки. Таким образом один поток не блокирует другие.

Многие видят в GIL слабость. Я же рассматриваю это как благо, ведь были созданы такие библиотеки, как NumPy, SciPy, которые занимают особое, уникальное положение в научном обществе.

Процессы (Processes)

Чтобы достичь параллелизма, в Python был добавлен модуль multiprocessing, который предоставляет API и выглядит очень похожим, если вы использовали threading раньше.

Давайте просто пойдем и изменим предыдущий пример. Теперь модифицированная версия использует Процесс вместо Потока.

import multiprocessing import time import random def worker(number): sleep = random.randrange(1, 10) time.sleep(sleep) print("I am Worker <>, I slept for <> seconds".format(number, sleep)) for i in range(5): t = multiprocessing.Process(target=worker, args=(i,)) t.start() print("All Processes are queued, let's see when they finish!")

Что же изменилось? Я просто импортировал модуль multiprocessing вместо threading. А затем, вместо потока я использовал процесс. Вот и всё! Теперь вместо множества потоков мы используем процессы, которые запускаются на разных ядрах CPU (если, конечно, у вашего процессора несколько ядер).

С помощью класса Pool мы также можем распределить выполнение одной функции между несколькими процессами для разных входных значений.

Пример из официальных документов:

from multiprocessing import Pool def f(x): return x*x if __name__ == '__main__': p = Pool(5) print(p.map(f, [1, 2, 3]))

Здесь вместо того, чтобы перебирать список значений и вызывать функцию f по одному, мы фактически запускаем функцию в разных процессах.

Один процесс выполняет f(1), другой-f(2), а другой-f (3). Наконец, результаты снова объединяются в список. Это позволяет нам разбить тяжелые вычисления на более мелкие части и запускать их параллельно для более быстрого расчета.

Модуль concurrent.futures

Модуль concurrent.futures большой и позволяет писать асинхронный код очень легко. Мои любимчики — ThreadPoolExecutor и ProcessPoolExecutor. Эти исполнители поддерживают пул потоков или процессов. Мы отправляем наши задачи в пул, и он запускает задачи в доступном потоке / процессе. Возвращается объект Future, который можно использовать для запроса и получения результата по завершении задачи.

А вот пример ThreadPoolExecutor:

from concurrent.futures import ThreadPoolExecutor from time import sleep def return_after_5_secs(message): sleep(5) return message pool = ThreadPoolExecutor(3) future = pool.submit(return_after_5_secs, ("hello")) print(future.done()) sleep(5) print(future.done()) print(future.result())

Asyncio — что, как и почему

У вас, вероятно, есть вопрос, который есть у многих людей в сообществе Python — что asyncio приносит нового? Зачем нужен был еще один способ асинхронного ввода-вывода? Разве у нас уже не было потоков и процессов?

Зачем нам нужен asyncio?

Процессы очень дорогостоящие и требуют много ресурсов для создания. Поэтому для операций ввода/вывода в основном выбираются потоки.

Мы знаем, что ввод-вывод зависит от внешних вещей — медленные диски или неприятные сетевые лаги делают ввод-вывод часто непредсказуемым. Теперь предположим, что мы используем потоки для операций ввода-вывода. 3 потока выполняют различные задачи ввода-вывода. Интерпретатор должен был бы переключаться между конкурентными потоками и давать каждому из них некоторое время по очереди.

Назовем потоки — T1, T2 и T3. Три потока начали свою операцию ввода-вывода. T3 завершает его первым. T2 и T1 все еще ожидают ввода-вывода. Интерпретатор Python переключается на T1, но он все еще ждет. Хорошо, интерпретатор перемещается в T2, а тот все еще ждет, а затем перемещается в T3, который готов и выполняет код. Вы видите в этом проблему?

T3 был готов, но интерпретатор сначала переключился между T2 и T1 — это понесло расходы на переключение, которых мы могли бы избежать, если бы интерпретатор сначала переключился на T3, верно?

Что есть asynio?

Asyncio предоставляет нам цикл событий наряду с другими крутыми вещами. Цикл событий (event loop) отслеживает события ввода/вывода и переключает задачи, которые готовы и ждут операции ввода/вывода.

Идея очень проста. Есть цикл обработки событий. И у нас есть функции, которые выполняют асинхронные операции ввода-вывода. Мы передаем свои функции циклу событий и просим его запустить их. Цикл событий возвращает нам объект Future, словно обещание, что в будущем мы что-то получим. Мы держимся за обещание, время от времени проверяем, имеет ли оно значение, и, наконец, когда значение получено, мы используем его в некоторых других операциях.

Как использовать asyncio?

Прежде чем мы начнём, давайте взглянем на пример:

import asyncio import datetime import random async def my_sleep_func(): await asyncio.sleep(random.randint(0, 5)) async def display_date(num, loop): end_time = loop.time() + 50.0 while True: print("Loop: <> Time: <>".format(num, datetime.datetime.now())) if (loop.time() + 1.0) >= end_time: break await my_sleep_func() loop = asyncio.get_event_loop() asyncio.ensure_future(display_date(1, loop)) asyncio.ensure_future(display_date(2, loop)) loop.run_forever()

Обратите внимание, что синтаксис async/await предназначен только для Python 3.5 и выше. Пройдёмся по коду:

  • У нас есть асинхронная функция display_date, которая принимает число (в качестве идентификатора) и цикл обработки событий в качестве параметров.
  • Функция имеет бесконечный цикл, который прерывается через 50 секунд. Но за этот период она неоднократно печатает время и делает паузу. Функция await может ожидать завершения выполнения других асинхронных функций (корутин).
  • Передаем функцию в цикл обработки событий (используя метод ensure_future).
  • Запускаем цикл событий.

Всякий раз, когда происходит вызов await, asyncio понимает, что функции, вероятно, потребуется некоторое время. Таким образом, он приостанавливает выполнение, начинает мониторинг любого связанного с ним события ввода-вывода и позволяет запускать задачи. Когда asyncio замечает, что приостановленный ввод-вывод функции готов, он возобновляет функцию.

Делаем правильный выбор

Только что мы прошлись по самым популярным формам конкурентности. Но остаётся вопрос — что следует выбрать?

Это зависит от вариантов использования. Из моего опыта я склонен следовать этому псевдо-коду:

if io_bound: if io_very_slow: print("Use Asyncio") else: print("Use Threads") else: print("Multi Processing")

Такие сложные материи, как асинхронность, мы проходим на обучении Рython ��

Что такое асинхронность в Python и как ее правильно применять

Моё мнение про Python

Основные аспекты изучения Python

Самые популярные библиотеки Python

Что должен знать Junior Python разработчик для устройства на работу

Среда разработки для Python: что это, какие они бывают и как их использовать

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

В контексте программирования, основанного на асинхронности, обычно используются специальные конструкции и механизмы, чтобы добиться эффективной обработки нескольких задач одновременно. Поговорим об этом подробнее.

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

  • Сетевые операции. При выполнении операций ввода-вывода, таких как запросы к базам данных или сетевые запросы, асинхронность позволяет выполнять множество таких операций параллельно, минимизируя время ожидания.
  • Параллельные вычисления. Асинхронность позволяет выполнять различные вычисления одновременно, что особенно полезно при обработке больших объемов данных или выполнении сложных вычислений.
  • Пользовательский интерфейс. В программировании с графическим интерфейсом асинхронность позволяет выполнять длительные операции (например, загрузку данных из сети) без блокирования пользовательского интерфейса.

�� Python — Язык Возможностей: Python — это ключ к созданию приложений, работающих везде, от веб-сайтов до искусственного интеллекта.

�� Курс Python Start от Foxminded: Независимо от вашего опыта, этот курс поможет вам освоить основы Python!

�� Программа Курса:

  • Урок 1: Введение и настройка.
  • Урок 2: Работа с данными.
  • Урок 3: Функции и файлы.
  • Урок 4: ООП и классы.
  • Урок 5: Продвинутые инструменты.

�� Сертификация: Получите официальный сертификат по окончании курса.

Как асинхронность реализуется в Python

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

Пример асинхронной функции в Python:

```python import asyncio async def fetch_data(url): print("Начало загрузки данных") await asyncio.sleep(3) # Имитация задержки при загрузке print("Данные загружены") async def main(): tasks = [fetch_data("http://example.com") for _ in range(5)] await asyncio.gather(*tasks) if __name__ == "__main__": asyncio.run(main()) ```

В данном примере функция `fetch_data` является асинхронной и имитирует загрузку данных с задержкой. Функция `main` создает несколько задач (корутин) и выполняет их асинхронно с помощью событийного цикла.

Асинхронность в Python – это мощный инструмент для улучшения производительности программы при работе с сетевыми операциями, вычислениями и другими асинхронными задачами. Однако асинхронность может быть сложной для понимания и управления. Поэтому использовать ее надо в случаях, когда задачи действительно могут выполняться параллельно и есть явная выгода от ее использования.

Асинхронное программирование в Python: принципы и концепции

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

Некоторые ключевые принципы и концепции асинхронного программирования в Python:

  1. Корутины (Coroutines) — это основной механизм асинхронного программирования в Python. Корутины представляют собой асинхронные функции, которые могут приостанавливать своё выполнение, позволяя другим корутинам запускаться в промежутках времени. Ключевое слово `async` используется для обозначения корутин.
```python async def my_coroutine(): # Асинхронные операции await asyncio.sleep(1) print("Корутина завершилась") ```
  1. Событийный цикл (Event Loop)- это основной механизм управления асинхронными задачами. Он работает как цикл, который постоянно проверяет состояние корутин и запускает их выполнение тогда, когда они готовы продолжить свою работу.
```python import asyncio async def main(): # Создаем событийный цикл loop = asyncio.get_event_loop() # Запускаем корутину в событийном цикле loop.create_task(my_coroutine()) # Запускаем событийный цикл loop.run_forever() # Вызываем функцию main asyncio.run(main()) ```
  1. Ключевое слово `await` используется в асинхронной функции для ожидания выполнения другой асинхронной операции. Функция `asyncio.sleep()` используется для имитации задержки в выполнении.
```python import asyncio async def my_coroutine(): print("Начало корутины") await asyncio.sleep(1) print("Корутина завершилась") asyncio.run(my_coroutine()) ```
  1. Асинхронные функции и объекты. В Python существует множество асинхронных функций и объектов в стандартной библиотеке и сторонних модулях, которые позволяют выполнять асинхронные операции, такие как сетевые запросы, базы данных, асинхронный ввод-вывод и другие.

Инструменты и библиотеки Python для асинхронного программирования

В Python существует несколько инструментов и библиотек, которые обеспечивают поддержку асинхронного программирования.

`asyncio`

`asyncio` — это стандартная библиотека Python, предназначенная для асинхронного программирования. Она включает в себя событийный цикл, который управляет асинхронными задачами и корутинами. `asyncio` предоставляет API для работы с сокетами, событиями, таймерами и другими асинхронными операциями.

`aiohttp`

`aiohttp` — это библиотека для выполнения асинхронных сетевых запросов. Она обеспечивает асинхронные клиенты HTTP и WebSocket, позволяя легко выполнять сетевые операции в асинхронном режиме.

`aiomysql`, `aiopg`

Это библиотеки для асинхронного взаимодействия с базами данных MySQL и PostgreSQL соответственно. Они позволяют выполнять запросы к базам данных асинхронно, что полезно при работе с большим количеством запросов.

Инструменты Python для асинхронного программирования

Похожие материалы

Моё мнение про Python

Основные аспекты изучения Python

Самые популярные библиотеки Python

Что должен знать Junior Python разработчик для устройства на работу

Среда разработки для Python: что это, какие они бывают и как их использовать

Что такое асинхронное программирование?

Это стиль программирования, при котором операции, которые могут занять много времени (например, ввод-вывод), выполняются параллельно основному потоку, не блокируя его.

Как в Python реализовать асинхронность?

В Python для асинхронного программирования используются ключевые слова async и await, а также библиотека asyncio.

В чем преимущества асинхронного программирования?

Асинхронность позволяет эффективно использовать ресурсы, особенно при операциях ввода-вывода, улучшая производительность и отзывчивость приложения.

Могу ли я использовать асинхронность с фреймворками вроде Django или Flask?

Flask поддерживает асинхронность начиная с версии 2.0. Django также начал внедрять асинхронные возможности, но полная асинхронность еще не реализована.

Что такое event loop в контексте асинхронного программирования?

Это центральная часть каждой асинхронной программы, которая определяет, какие задачи следует выполнить и когда.

Что такое coroutines в Python?

Coroutines — это специальные функции, которые могут приостанавливать свое выполнение и передавать управление обратно в event loop, ожидая выполнения другой операции.

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *