Comments 12
В разделе про базы данных зачем-то заново дан пример по aiohttp...
Ох, OTUS- символ низкокачественных статей на Хабре... Снова неправильный пример, скопированный откуда-то из глубин индийского интернета..
Держите правильный код, просто дарю. Можете в статье поправить (да, в обоих местах).
Пояснение: в изначальном примере сессия создается внутри функции fetch_data
, что ведет к очень большим накладным расходам - создание нового TCP-соединения. Если сессию сначала создать, а потом передать в функцию - можно добиться более высокой производительности и снижения нагрузок на сеть и сервера. Вот просто первая попавшаяся нагугленная статья по теме. Вообще ClientSession принимает много параметров и их нужно использовать если у вас что-то больше чем просто один раз скачать одну страничку.
Однако, XXI век не стоит на дворе и пора бы переходить с aiohttp на httpx.
import aiohttp
import asyncio
async def fetch_data(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
urls = [
"https://api.example.com/data/1",
"https://api.example.com/data/2",
"https://api.example.com/data/3"
]
async with aiohttp.ClientSession() as session:
tasks = [fetch_data(session, url) for url in urls]
results = await asyncio.gather(*tasks)
for result in results:
print(result)
asyncio.run(main())
Вы оказались безусловно правы. Исправил код, а также указал ваше авторство этого кода. Спасибо, что развиваете наше сообщество!
А почему httpx
ставите выше aiohttp
?
Сразу видно что вы только что вернулись с очередного code review :)
Во-первых, вы, думаю, правы. Хотя, с точки зрения языка, разницы нет, но с точки зрения красоты оформления кода - лучше сначала импортировать системные библиотеки, потом добавить пустую строку, а затем дополнительные библиотеки.
Однако, во-вторых, это не мой пример, я взял код из статьи и поменял пару строк.
Заявка на тему следующей статьи - межмикросервисное взаимодействие
Я правильно понимаю что в пайтане(фастапи) получается все запросы будут обрабатываться последовательно до момента когда будет создан новый поток от async/await и потом после обработки опять нужен будет основной поток для продолжения , который так же будет по очереди обрабатывать все завершения?
(взгляд из asp.net web api - у нас на каждый запрос создается новый поток, всё работает в параллель)
Да, все выполняется в один aio-поток и await - это место где он может переключиться пока ждет ответа от сети, например. В Python нельзя использовать больше одного cpu core в приложении, даже если вы создаете несколько потоков (threads), поэтому даже потоки выполняются по очереди, но их переключает уже интерпретатор. Для использования нескольких процессоров используют запуск нескольких экземпляров приложения и синхронизацией между ними (если нужно). Тот же FastAPI не требует синхронизации (разные независимые запросы). Однако, большинство долгих операций - это как раз IO-операции (сеть, БД) и async/await подход работает неплохо.
Если же приложение постоянно делит тяжелые матрицы - то ему не помогут async/await.
В этом примере мы используем библиотеку
aiohttp
для выполнения асинхронных HTTP-запросов к нескольким URL-адресам. Когда мы вызываемasyncio.gather(*tasks)
, все запросы выполняются параллельно, и после того, как все они завершатся, мы получаем результаты.
А разве asyncio.gather(*tasks)
это не про конкурентность? Параллельность это всеже немного другое.
aiomultiprocess
вот тут про параллельность согласен
OTUS, тут дело пишут, надо бы поправить статью...
Асинхронные микросервисы на Python