Эта статья живет в:
- Dev.to
- Середина
- GitHub
- Документы Fastapi (включая переводы на другие языки)
вступление
Современные версии Python (и других языков) имеют поддержку “Асинхронный код” Используя что -то называемое “Coroutines” , с асинхро
и ждет
синтаксис.
Вот дружеское и не очень техническое объяснение, чтобы дать некоторую интуицию обо всем этом, включая асинхронный код, параллелизм и параллелизм.
Это взято из Документы для FASTAPI , современная структура для строительства API в Python.
Хотя это было написано для Python и Fastapi, вся история и информация актуальна для других языков, которые также имеют Асинхронизация
и ждет
, как JavaScript и Ржавчина Анкет
Теперь давайте посмотрим эту фразу по частям в разделах ниже:
- Асинхронный код
асинхро
а такжеЖдите
- Кораки
Асинхронный код
Асинхронный код просто означает, что язык 💬 имеет способ сказать компьютер/программу 🤖, что в какой -то момент в коде он должен будет ждать что -то еще чтобы закончить где -нибудь еще. Допустим, что что -то еще называется «медленным» 📝.
Таким образом, в течение этого времени компьютер может пойти и выполнять какую-то другую работу, а «медленная» заканчивается.
Затем компьютер/программа 🤖 возвращается каждый раз, когда у него есть шанс, потому что он снова ждет, или всякий раз, когда он завершал всю работу, которую он выполнял в этот момент. И он увидит, что какая -либо из задач, которых она ждала, уже закончила, делая все, что должно было сделать.
Затем, для завершения первой задачи требуется первая задача (скажем, наше «медленное» 📝) и продолжает все, что это было связано с этим.
Это «жди чего -то другого» обычно относится к I/O Операции, которые относительно «медленные» (по сравнению со скоростью процессора и памяти оперативной памяти, например, ожидание:
- Данные от клиента будут отправлены через сеть
- Данные, отправленные вашей программой, будут получены клиентом через сеть
- Содержимое файла на диске, которое будет прочитать систему и предоставленную вашей программе
- Содержание, которое ваша программа дала системе, которая будет написана на диск
- удаленная операция API
- операция базы данных для завершения
- Запрос базы данных для возврата результатов
- и т.п.
Поскольку время исполнения потребляется в основном в ожидании I/O Операции, они называют их операциями «связанные с вводом/выводом».
Он называется «асинхронным», потому что компьютер/программа не обязательно «синхронизироваться» с медленной задачей, ожидая точного момента, когда задача завершает, не делая ничего, чтобы иметь возможность взять результат задачи и продолжить работу Анкет
Вместо этого, будучи «асинхронной» системой, после завершения задания может немного подождать в очереди (некоторые микросекунд), чтобы компьютер/программа закончил все, что пошло, а затем вернуться, чтобы получить результаты и Продолжайте работать с ними.
Для «синхронного» (в отличие от «асинхронного») они обычно также используют термин «последовательный», потому что компьютер/программа выполняет все шаги последовательности перед переходом на другую задачу, даже если эти шаги включают ожидание.
Параллелизм и гамбургеры
Эта идея асинхронно Код, описанный выше, также иногда называется “Согласно параллелизму” Анкет Это отличается от «Параллелизм» Анкет
Параллелизм и Параллелизм Оба относятся к «разным вещам, происходящим более или менее одновременно».
Но детали между параллелизм и Параллелизм совершенно разные.
Чтобы увидеть разницу, представьте себе следующую историю о гамбургерах:
Одновременные гамбургеры
Вы идете со своей влюбленностью, чтобы получить фаст -фуд 🍔, вы стоите в очереди, в то время как кассир 💁 берет заказы у людей перед вами.
Тогда ваша очередь, вы размещаете свой заказ из 2 очень модных гамбургеров 🍔 для вашей влюбленности и вас.
Вы платите 💸.
Кассир 💁 что -то говорит парню на кухне 👨 🍳 Поэтому он знает, что должен подготовить ваши гамбургеры 🍔 (хотя он в настоящее время готовит их к предыдущим клиентам).
Кассир 💁 дает вам номер вашей очереди.
Пока вы ждете, вы идете со своей влюбленностью и выбираете стол, вы сидите и говорите со своей влюбленностью в течение долгого времени (так как ваши гамбургеры очень причудливы и уделите некоторое время, чтобы подготовиться ✨🍔✨).
Когда вы сидите на столе со своей влюбленностью 😍, пока вы ждете гамбургеров 🍔, вы можете потратить это время, восхищаясь тем, насколько классной, милой и умной является ваша влюбленность ✨😍✨.
В ожидании и разговоре со своей влюбленностью, время от времени вы проверяете номер, отображаемый на стойке, чтобы увидеть, является ли ваша очередь.
Затем в какой -то момент это наконец -то ваша очередь. Вы идете к стойке, получаете свои гамбургеры 🍔 и возвращаетесь к столу.
Вы и ваша влюбленность 😍 есть гамбургеры 🍔 и хорошо провести время ✨.
Представьте, что вы компьютер/программа 🤖 В этой истории.
Пока вы находитесь на линии, вы просто простаиваете 😴, ожидая своей очереди, не делая ничего очень «продуктивного». Но линия быстрая, потому что кассир 💁 принимает только заказы (не готовит их), так что это нормально.
Затем, когда наступит ваша очередь, вы выполняете фактическую «продуктивную» работу 🤓, вы обрабатываете меню, решаете, что вы хотите, получаете свой выбор, заплатите 💸, проверьте, что вы даете правильный счет или карту, проверьте, что вас взимаете правильно, проверьте, что заказ имеет правильные элементы и т. Д.
Но тогда, даже если у вас все еще нет ваших гамбургеров 🍔 🍔 🍔 🍔, ваша работа с кассиром 💁 «на паузе», потому что вам нужно ждать 🕙, чтобы ваши гамбургеры были готовы.
But as you go away from the counter and sit on the table with a number for your turn, you can switch 🔀 your attention to your crush 😍, and “work” ⏯ 🤓 on that. Тогда вы снова делаете что -то очень «продуктивное» 🤓 🤓, как и флиртование с вашей влюбленностью.
Тогда кассир 💁 говорит: «Я закончил делать гамбургеры» 🍔 🍔, поместив свой номер на дисплее прилавка, но вы не сразу же сразу же прыгаете, когда отображаемый номер изменяется на ваш ход. Вы знаете, что никто не украдет ваши гамбургеры 🍔, потому что у вас есть количество вашей очереди, и у них есть их.
Таким образом, вы ждете, пока ваша влюбленность закончит историю (завершить текущую работу ⏯/задача, которая обрабатывается 🤓), мягко улыбнитесь и скажите, что вы собираетесь за гамбургеры.
Затем вы идете к счетчику 🔀, к первоначальной задаче, которая теперь завершена, выберите гамбургеры 🍔, скажите спасибо и возьмите их к столу. Это завершает этот шаг/задача взаимодействия с счетчиком ⏹. Это, в свою очередь, создает новую задачу «eating Burgers» ⏯ ⏯, но предыдущий из «получения гамбургеров» завершена ⏹.
Параллельные гамбургеры
Теперь давайте представим, что это не «одновременные гамбургеры», а «параллельные гамбургеры».
Вы идете со своей влюбленностью, чтобы получить параллельный фаст -фуд 🍔.
Вы стоите в очереди, в то время как несколько (скажем, 8) кассиров, которые в то же время являются поварами 👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳 Возьмите заказы у людей перед вами.
Все перед тем, как вы ждали 🕙, чтобы их гамбургеры были готовы, прежде чем покинуть счетчик, потому что каждый из 8 кассиров идет сам и сразу готовит бургер, прежде чем получить следующий заказ.
Затем, наконец, ваша очередь, вы размещаете свой заказ из 2 очень модных гамбургеров 🍔 для вашей влюбленности и вас.
Вы платите 💸.
Кассир идет на кухню 👨🍳.
Вы ждете, стоя перед стойкой 🕙, так что никто другой не берет ваши гамбургеры 🍔, прежде чем вы это сделаете, так как нет цифр для поворотов.
Поскольку вы и ваша влюбленность заняты, не позволяя никому оказаться перед вами и не принимать свои гамбургеры, когда они прибывают 🕙, вы не можете обратить внимание на свою влюбленность ».
Это «синхронная» работа, вы «синхронизированы» с кассиром/поваром 👨🍳. Вы должны подождать 🕙 и быть там в тот момент, когда кассир/повар заканчивает гамбургеры 🍔 и дает их вам, или иным образом, кто -то другой может их взять.
Затем ваш кассир/повар 👨🍳, наконец, возвращается с вашими гамбургерами 🍔, после долгого ожидания 🕙 перед прилавками.
Вы берете свои гамбургеры 🍔 и идете к столу со своей влюбленностью 😍.
Вы просто едите их, и вы закончили 🍔 ⏹.
Не было много разговоров или флирта, так как большую часть времени было потрачено на ожидание 🕙 перед стойкой 😞.
В этом сценарии параллельных гамбургеров вы являетесь компьютером/программой 🤖 с двумя процессорами (вы и ваша влюбленность), оба ожидая 🕙 и уделяете их вниманию ⏯, чтобы «ждать на прилавке» 🕙 надолго.
В магазине быстрого питания есть 8 процессоров (кассиры/повара) 👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳. В то время как в одновременном магазине гамбургеров могло быть всего 2 (один кассир и один повар) 💁 👨🍳 👨🍳 👨🍳 👨🍳 👨🍳 👨🍳 👨🍳 👨🍳 👨🍳 👨🍳
Но, тем не менее, последний опыт не самый лучший 😞.
Это была бы параллельная эквивалентная история для гамбургеров 🍔.
Для более «реальной жизни» примера этого представьте банк.
В последнее время у большинства банков было несколько кассиров 👨💼👨💼👨💼👨💼 и большая линия 🕙🕙🕙🕙🕙🕙🕙🕙.
Все кассиры выполняют всю работу с одним клиентом после другого 👨💼⏯.
И вы должны ждать 🕙 в течение долгого времени или вы теряете свою очередь.
Вы, вероятно, не захотите брать с собой влюбленность, чтобы выполнить поручения в банке 🏦.
Вывод гамбургера
В этом сценарии «Бургеров быстрого питания с вашей влюбленностью», так как есть много ожидания 🕙, имеет гораздо больше смысла иметь одновременную систему ⏸🔀⏯.
Это относится к большинству веб -приложений.
Многие, многие пользователи, но ваш сервер ждет 🕙 для их не очень хорошего соединения, чтобы отправить их запросы.
А потом ждем 🕙 снова, чтобы ответы вернулись.
Это «ожидание» 🕙 измеряется в микросекундах, но все же, суммируя все это, в конце концов, это много ожидания.
Вот почему имеет большой смысл использовать асинхронный ⏸🔀⏯ код для веб -API.
Большинство существующих популярных рамок Python (включая Flask и Django) были созданы до того, как существовали новые асинхронные особенности в Python. Таким образом, способы, которыми они могут быть развернуты параллельным выполнением поддержки, и более старую форму асинхронного выполнения, которая не так мощна, как новые возможности.
Несмотря на то, что в Django была разработана основная спецификация для асинхронного веб -питона (ASGI), чтобы добавить поддержку веб -кокеты.
Такая асинхронность – это то, что делало Nodejs популярными (хотя Nodejs не параллельно), и это сила Go как языка программирования.
И это тот же уровень производительности, который вы получаете с FASTAPI Анкет
И, поскольку вы можете иметь параллелизм и асинхронность одновременно, вы получаете более высокую производительность, чем большинство тестируемых рамок Nodejs, и наравне с GO, который является составленным языком, ближе к C (Все спасибо Starlette) .
Параллелизм лучше ли параллелизм?
Неа! Это не мораль истории.
Параллелизм отличается от параллелизма. И это лучше на конкретный Сценарии, которые включают в себя много ожидания. Из -за этого это, как правило, намного лучше, чем параллелизм для разработки веб -приложений. Но не для всего.
Итак, чтобы сбалансировать это, представьте себе следующий рассказ:
Вы должны почистить большой грязный дом.
Да, это вся история Анкет
Там нет никакого ожидания 🕙 где бы то ни было, просто много работы, в нескольких местах дома.
У вас могут быть повороты, как в примере гамбургеров, сначала в гостиной, затем на кухне, но, поскольку вы не ждете ничего, просто чистка и уборка, повороты ничего не повлияют на то.
Чтобы закончить или без поворотов (параллелизм) потребуется столько времени, и вы бы проделали столько же работы.
Но в этом случае, если бы вы могли принести 8 бывших каштаных/поваров/теперь чистотеров 👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳, и каждый из них (плюс вы) могли взять зону дома, чтобы очистить его, вы можете выполнить всю работу в параллель , с дополнительной помощью, и закончить гораздо раньше.
В этом сценарии каждый из чистящих средств (включая вас) будет процессором, выполняющим свою часть работы.
И поскольку большая часть времени выполнения принимается по фактической работе (вместо ожидания), а работа на компьютере выполняется Процессор , они называют эти проблемы «связанным с процессором».
Общие примеры операций, связанных с границей ЦП, – это вещи, которые требуют сложной математической обработки.
Например:
- Аудио или Обработка изображений Анкет
- Компьютерное зрение : изображение состоит из миллионов пикселей, каждый пиксель имеет 3 значения/цвета, обработка, которая обычно требует вычисления чего -либо на этих пикселях, все это одновременно.
- Машинное обучение : Обычно требуется много умножений «матрицы» и «вектора». Подумайте об огромной электронной таблице с числами и умножением их всех вместе.
- Глубокое обучение : Это подполе машинного обучения, так что применимо. Просто не существует ни одной электронной таблицы чисел для умножения, но огромный набор из них, и во многих случаях вы используете специальный процессор для создания и/или использования этих моделей.
Параллелизм + параллелизм: веб -сайт + машинное обучение
С FASTAPI Вы можете воспользоваться преимуществами параллелизма, который очень распространен для веб -разработки (то же самое основное привлекательное из Nodejs).
Но вы также можете использовать преимущества параллелизма и многопроцессы (имея несколько процессов, работающих параллельно) для ЦП связан Рабочие нагрузки, как и в системах машинного обучения.
Это, плюс простой факт, что Python является основным языком для Наука данных Машинное обучение и особенно глубокое обучение, делают FastAPI очень хорошим совпадением для веб -API и приложений и приложений машинного обучения в области данных/машинного обучения (среди многих других).
Чтобы увидеть, как достичь этого параллелизма в производстве, см. Docs Fastapi для развертывания Анкет
асинхронно и ждет
Современные версии Python имеют очень интуитивно понятный способ определения асинхронного кода. Это делает его похожим на обычный «последовательный» код и делает «ожидание» для вас в нужные моменты.
Когда есть операция, которая потребует ожидания, прежде чем предоставить результаты, и будет поддержать эти новые функции Python, вы можете кодировать ее как:
burgers = await get_burgers(2)
Ключ здесь – Ждите
. Он говорит Python, что должен ждать ⏸ для get_burgers (2)
Чтобы закончить делать свое дело, прежде чем хранить результаты в Бургеры
Анкет With that, Python will know that it can go and do something else 🔀 ⏯ in the meanwhile (like receiving another request).
Для ждет
Чтобы работать, это должно быть внутри функции, которая поддерживает эту асинхронность. Для этого вы просто объявите это асинхромат def
:
async def get_burgers(number: int): # Do some asynchronous stuff to create the burgers return burgers
… вместо def
:
# This is not asynchronous def get_sequential_burgers(number: int): # Do some sequential stuff to create the burgers return burgers
С асинхромат def
, Python знает, что внутри этой функции он должен знать о ждет
выражения, и что он может «приостановить» ⏸ выполнение этой функции и пойти что -нибудь еще 🔀, прежде чем вернуться.
Когда вы хотите позвонить асинхромат def
Функция, вы должны «ждать» этого. Так что это не сработает:
# This won't work, because get_burgers was defined with: async def burgers = get_burgers(2)
Другие формы асинхронного кода
Этот стиль использования Асинхронизация
и ждет
относительно новый на языке.
Но это делает работу с асинхронным кодом намного проще.
Этот же синтаксис (или почти идентичный) был также включен недавно в современные версии JavaScript (в браузере и Nodejs).
Но до этого обработка асинхронного кода была довольно сложной и трудной.
В предыдущих версиях Python вы могли бы использовать потоки или Gevent Анкет Но код гораздо сложнее понять, отлаживать и думать.
В предыдущих версиях Nodejs/Browser JavaScript вы бы использовали «обратные вызовы». Что приводит к обратный вызовой ад .
Кораки
Coroutine это просто очень причудливый термин для вещи, возвращенной асинхромат def
функция Python знает, что это что -то вроде функции, которую он может начать, и что в какой -то момент она закончится, но она также может быть приостановлена ⏸ внутри, всякий раз, когда есть Ждите
внутри.
Но вся эта функциональность использования асинхронного кода с Асинхронизация
и ждет
много раз обобщено как использование «Coroutines». Это сопоставимо с основной ключевой особенностью GO, «Goroutines».
Вывод
Давайте посмотрим ту же фразу сверху:
Современные версии Python имеют поддержку “Асинхронный код” Используя что -то называемое “Coroutines” , с асинхро
и ждет
синтаксис.
Это должно иметь больше смысла сейчас. ✨
Все это то, что способствует Fastapi (через Starlette) и что делает его такими впечатляющими результатами.
Учить больше
В этой версии есть некоторые детали, которые очень специфичны для Fastapi. Если вы хотите изучить их, в том числе как получить асинхронные преимущества производительности, в то же время писать стандарт def
функции и использование стандартных библиотек, проверьте Fastapi Docs Анкет
Если вы хотите более глубокого и гораздо более технического объяснения всего этого, проверьте это Видеоспись от EdgedB по Lłukasz Langa Анкет
Обо мне
Привет! 👋 Я Себастьян Рамирес ( tiangolo ).
Вы можете следить за мной, связываться со мной, задавать вопросы, посмотреть, что я делаю, или используйте мой открытый исходный код:
- GitHub: Tiangolo
- Twitter: Tiangolo
- LinkedIn: Tiangolo
- Dev: Tiangolo.to
- Середина: Tiangolo
- Интернет: tiangolo.com
Оригинал: “https://dev.to/tiangolo/concurrent-burgers-understand-async-await-3n20”