В мире программирования широко распространена концепция «неблокировки». Разработчики JavaScript часто используют термин «асинхронный», поскольку это одна из сильных сторон JavaScript. Однако, чтобы по-настоящему понять асинхронное программирование, важно усвоить концепции параллельного и параллельного программирования.
Когда несколько независимых объектов работают одновременно, программирование происходит одновременно. Это не обязательно означает, что эти задачи выполняются одновременно. Вместо этого это означает, что задачи выполняются с течением времени за счет совместного использования ресурсов, таких как время ЦП. Основным преимуществом параллельного программирования является его надежность: если один процесс выходит из строя, остальная часть вашей программы продолжает работать.
Если алгоритм может разделить свою работу на несколько частей, он является параллельным. Чем больше у вас процессоров, тем больше выгоды вы получаете от параллелизма. Эффективное параллельное программирование оптимизирует ресурсы современных машин для повышения производительности.
Пример параллелизма:
Представьте, что вы готовите блюдо, требующее поджарить мясо и приготовить соус. Вы начинаете с того, что кладете мясо на гриль. Пока мясо жарится на гриле, нарежьте помидоры и другие овощи для соуса. Затем вы начинаете варить соус, время от времени проверяя мясо. Здесь обе задачи (жарка мяса и приготовление соуса) выполняются, но вы переключаете свое внимание между ними. Это представляет собой параллелизм.
Пример параллелизма:
Теперь предположим, что у вас есть друг, который может вам помочь. Пока вы готовите мясо на гриле, ваш друг готовит соус. Обе задачи выполняются одновременно без необходимости переключения внимания между ними. Это представляет собой параллелизм.
Асинхронное программирование включает в себя обработку операций ввода-вывода (I/O), которые происходят вне вашей программы, таких как пользовательский ввод, печать на терминале, чтение из сокета или запись на диск. Ключевые характеристики асинхронного ввода-вывода:
Время, затраченное на операцию, не зависит от процессора. Вместо этого это зависит от таких факторов, как скорость диска, задержка сети и другие внешние условия.
Программа не может предсказать, когда завершится операция.
Для сервисов со значительным объемом ввода-вывода (например, веб-серверов, баз данных и сценариев развертывания) оптимизация этих операций может значительно повысить производительность.
Давайте посмотрим примеры блокирующего и неблокирующего кода.
Рассмотрим простую программу:
import time def task(): time.sleep(2) print("Hello") for _ in range(3): task()
В этой синхронной программе каждая задача ожидает завершения предыдущей, что приводит к задержкам.
Теперь давайте посмотрим на асинхронную версию с использованием asyncio:
import asyncio async def task(): await asyncio.sleep(2) print("Hello") async def main(): tasks = [task() for _ in range(3)] await asyncio.gather(*tasks) asyncio.run(main())
В этой асинхронной программе задачи выполняются одновременно, что сокращает общее время выполнения. Давайте рассмотрим компоненты асинхронного программирования.
Циклы событий, сопрограммы и фьючерсы — важнейшие элементы асинхронной программы Python.
Цикл событий: Управляет переключением задач и потоком выполнения, отслеживая задачи, которые должны выполняться асинхронно.
Сопрограммы: Специальные функции, которые можно приостанавливать и возобновлять, позволяя запускать другие задачи во время ожидания. Сопрограмма указывает, где в функции должно произойти событие переключения задач, возвращая управление циклу событий. Сопрограммы обычно создаются циклом событий и сохраняются внутри в очереди задач.
Futures: Заполнители для результатов сопрограмм, сохраняющие результат или исключения. Как только цикл событий инициирует сопрограмму, создается соответствующее будущее, в котором сохраняется результат сопрограммы или исключение, если оно было создано во время выполнения сопрограммы.
После объяснения важнейших частей асинхронного программирования на Python давайте напишем немного кода.
Теперь, когда вы понимаете шаблон асинхронного программирования, давайте напишем небольшой скрипт и проанализируем его выполнение. Вот простой асинхронный скрипт:
import asyncio async def task(): await asyncio.sleep(2) print("Hello") async def main(): tasks = [task() for _ in range(3)] await asyncio.gather(*tasks) asyncio.run(main())
В приведенном выше коде мы пытаемся продолжить выполнение других задач, даже если другая выполняемая задача находится в спящем режиме (блокируется). Обратите внимание на ключевое слово async перед задачей и основными функциями.
Эти функции теперь являются сопрограммами.
Функциям сопрограмм в Python предшествует ключевое слово async. Функция main() здесь является координатором задач или нашим единственным циклом событий, поскольку она выполняет все задачи с использованием метода async.gather. Функция asyncio.gather одновременно запускает ожидаемые объекты.
Выход:
Hello Hello Hello Program executed in 2.01 seconds.
Когда каждая задача достигает await asyncio.sleep(2), она просто переходит к следующей задаче и возвращается после ее завершения. Это все равно, что сказать: «Я засну на 2 секунды. Сделай что-нибудь еще».
Давайте посмотрим синхронную версию для быстрого сравнения.
import time def task(): time.sleep(2) print("Hello") for _ in range(3): task()
В приведенном выше коде мы идем традиционным путем программирования на Python. Вы заметите, что выполнение процесса займет гораздо больше времени.
Выход:
Hello Hello Hello Program executed in 6.01 seconds.
Теперь вы можете заметить время выполнения. Думайте о time.sleep() как о блокирующей задаче, а о asyncio.sleep() как о неблокирующей или длительной задаче. В асинхронном программировании преимущество ожидания чего-либо, например asyncio.sleep(), заключается в том, что окружающая функция может временно передать управление другой функции, которая готова к немедленному выполнению.
Поняв некоторые базовые примеры асинхронного программирования на Python, давайте изучим правила асинхронного программирования на Python.
Сопрограммы: Сопрограммы не могут выполняться напрямую. Если вы попытаетесь запустить функцию сопрограммы напрямую, она вернет объект сопрограммы. Вместо этого используйте asyncio.run():
import asyncio async def hello(): await asyncio.sleep(1) print('Hello') asyncio.run(hello())
Ожидаемые объекты: Сопрограммы, фьючерсы и задачи — это основные ожидаемые объекты. Сопрограммы Python являются ожидаемыми, и их можно ожидать от других сопрограмм.
Ключевое слово Await:await можно использовать только в асинхронных функциях.
async def hello(): await asyncio.sleep(1) print("Hello")
Совместимость: Не все модули Python совместимы с асинхронным программированием. Например, замена await asyncio.sleep() на time.sleep() приведет к ошибке. Вы можете проверить список совместимых и поддерживаемых модулей здесь.
В следующем разделе мы рассмотрим распространенное использование асинхронного программирования — HTTP-запросы.
Давайте посмотрим на следующий фрагмент кода:
import aiohttp import asyncio async def fetch(session, city): url = f"https://www.prevision-meteo.ch/services/json/{city}" async with session.get(url) as response: data = await response.json() print(f"Temperature at {city}: {data['current_condition']['tmp']} C") async def main(): async with aiohttp.ClientSession() as session: cities = ['paris', 'toulouse', 'marseille'] tasks = [fetch(session, city) for city in cities] await asyncio.gather(*tasks) asyncio.run(main())
В приведенном выше коде мы создаем две асинхронные функции: одну для получения данных из URL-адреса prevision-meteo и основную функцию для выполнения процессов в коде Python. Цель состоит в том, чтобы отправлять асинхронные HTTP-запросы GET для получения данных о температуре и печати ответов.
В функциях main и fetch мы используем async. В функции выборки async with гарантирует правильное закрытие соединения. В основной функции он гарантирует закрытие ClientSession после завершения запросов. Эти методы важны при асинхронном кодировании на Python для эффективного управления ресурсами и предотвращения утечек.
В последней строке основной функции мы используем await asyncio.gather(*tasks). В нашем случае все задачи выполняются одновременно, что позволяет программе одновременно отправлять несколько HTTP-запросов. Использование await гарантирует, что программа ожидает завершения всех задач, прежде чем продолжить.
Выход:
Temperature at marseille: 25 C Temperature at toulouse: 24 C Temperature at paris: 18 C Program executed in 5.86 seconds.
Код:
import requests import time def fetch(city): url = f"https://www.prevision-meteo.ch/services/json/{city}" response = requests.get(url) data = response.json() print(f"Temperature at {city}: {data['current_condition']['tmp']} C") def main(): cities = ['paris', 'toulouse', 'marseille'] for city in cities: fetch(city) start_time = time.time() main() print(f"Program executed in {time.time() - start_time:.2f} seconds.")
Выход:
Temperature at Paris: 18 C Temperature at Toulouse: 24 C Temperature at Marseille: 25 C Program executed in 9.01 seconds.
Асинхронная модель работает лучше всего, когда:
Существует большое количество задач, поэтому хотя бы одна задача всегда может быть выполнена.
Задачи требуют значительного объема операций ввода-вывода, в результате чего асинхронная программа тратит много времени на блокировку, когда могут выполняться другие задачи.
Задачи в значительной степени независимы, что сводит к минимуму взаимодействие между задачами (и, следовательно, одна задача ожидает выполнения другой).
В этом уроке мы рассмотрели:
Концепции асинхронного программирования и связанные с ним концепции.
Эффективное использование async/await.
Выполнение асинхронных HTTP-запросов с помощью aiohttp.
Преимущества асинхронного программирования.
Спасибо, что прочитали. Вторая часть будет посвящена асинхронному программированию с помощью Django.
Документация Python: сопрограммы и задачи
Документация по Python: asyncio — асинхронный ввод-вывод
Документация aiohttp
Библиотеки Aio
параллелизм против параллелизма
Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.
Copyright© 2022 湘ICP备2022001581号-3