Как стать автором
Обновить

Комментарии 12

А какого года оригинал?

aiohttp вовсю использует менеджер контекста и модуль async_timeout.

Upd. Увидел спойлер )
Тема интересная, но для новичка в этой области (меня например) сложновато. Есть более простой способ параллельного выполнения задач типа скачивания чего из интернета или отправки запросов в веб-сервис toly.github.io/blog/2014/02/13/parallelism-in-one-line использовал его и не раз, результатом доволен. Пишешь и отлаживаешь функцию, потом оборачиваешь ее и работает.

Да, этот способ проще. Но у него есть несколько важных ограничений:


  1. Нужно следить, чтобы эта функция не записывала ничего в общие объекты.
  2. Количество потоков не может быть слишком большим (10 — нормально, 1000 — еще сойдет, 100 000 — лучше не надо)
>Есть более простой способ параллельного выполнения задач

Он проще разве что для списка из простых задач. Когда надо будет сделать что-то немного посложнее, начнётся callback hell.
Непонятно почему питон пошел по пути async-await, вместо того чтобы развивать направление gevent/greenlet, посути шаг назад. С зелеными тредами структура програм проще, гораздо мешьше корневого функционала, что понижает сложность, лучше совместимость между библиотекми, ещё можно про ORM вспомнить.

К тому же, из-за хайпа, многие используют asyncio не по назначению (например толстые веб сервера или бизнес логику), или вот пример, где asyncio оказался медленнее «блокирующего» кода в 5* раз.
Потому что одно не отменяет другое, gevent — это немного не про то, про что async-await. Например, если у вас есть async def getUserByID(id) и массив ids, то с async-await вы в 1 строчку получаете всех юзеров по их id из массива параллельно через await wait([getUserByID(id) for id in ids]). В случае же gevent синтаксис был бы гораздо более тяжелый — пришлось бы стартовать для каждого id по гринлету, потом дожидаться их всех окончания, а исключение в любом из них пробрасывать наружу.
gevent — это немного не про то, про что async-await
Цель у них одна и та же.

await wait([getUserByID(id) for id in ids]). В случае же gevent синтаксис был бы гораздо более тяжелый
Нет, с gevent этот пример может быть таким:
wait([getUserByID(id) for id in ids])
где getUserByID с декоратором «async», т.е. аналогично, но в gevent можно более продуктивно т.к. не нужно раскрашивать функции в разные цвета, в отличие от asyncio.

а исключение в любом из них пробрасывать наружу.
Исключения как раз там работают нормально, а вот для asyncio, который был внешней либой, пришлось расширять синтаксис питона, дорабатывать проборос исключений через yield from, да и сам yield from создали по большей части для asyncio, но в последствии его забросили и перешли на async await. Т.е. посути из-за одной либы изнасиловали питон.

В целом же asyncio не плох, есть куча либ, я использую его в своих проектах, но все же это не та дорога, не «Simple is better than complex».

Вот ещё статья в ту же сторону I don't understand Python's Asyncio
Корутины содержат операторы yield, с помощью которых мы определяем места, где можно переключиться на другие ожидающие выполнения задачи.
За переключение контекста в asyncio отвечает, который передаёт управление обратно в event loop, а тот в свою очередь — к другой корутине.

Небольшая неточность, для переключения контекста await используется, а не yield как в Twisted например. В оригинальной статье слово yield используется, но не как команда, а как просто слово «уступать»
Спасибо за перевод!
К сожалению приведенные примеры устарели и в python 3.6 c 3-й версией aiohttp вариант
 response = await aiohttp.request('GET', service.url)
вызывает ошибку.

Unclosed client session

В Git работающий вариант.

Интересно, что python 3.5 и версия
>>> aiohttp.__version__
'2.3.10'

отрабатывает нормально и тот код, что в статье

Где-то хихикает один goшник)))

Ему бы плакать

Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории