Comments 6
Супер интересно. Спасибо!
Насколько я помню, в корутинах (а точнее, их реализации через генераторы) идёт возвращение значения из цикла. В псевдокоде это что-то типа:
res = task.send(None)
while not finished:
res = tasl.send(res)
return resВ step я такого не увидел. Я так понимаю, там всегда создаётся новая таска и она либо выполняется, либо нет.
Тогда было бы недурно освятить работу с сокетами, а именно, как они догадываются, что сокет ответил и завершил передачу.
Спасибо за комментарий!
По поводу сокетов. Да, это отдельная большая тема, которую я разбирал в предыдущей статье про механику событийного цикла. Если коротко: сама операционная система (через epoll в Линуксе, kqueue на Маке и т.д.) следит за файловыми дескрипторами, и когда сокет готов отдать данные, событийный цикл получает уведомление, завершает нужный фьючер, тот через колбэк будит таску.
По поводу send(res). Тут есть тонкость. В asyncio Task.__step всегда вызывает coro.send(None), а не coro.send(result) (соответствующий фрагмент кода есть в статье). Когда таска останавливается на await future, она подписывает свой метод __wakeup на завершение этого фьючера через add_done_callback() и засыпает. Дальше инициатива переходит к фьючеру: когда он завершается, он сам обходит свои коллбэки и через call_soon() закидывает вызов __wakeup тасок, которые подписались на этот фьючер, в очередь цикла событий. Цикл вызывает __wakeup таски, тот вызывает __step и таска продолжает выполнение с того места, где остановилась, вызывая у корутины все тот же coro.send(None). Результат завершившегося фьючера корутина получает не через аргумент send(), а через return self.result() внутри Future.__await__ при возобновлении. Поэтому новая таска при каждом шаге не создается, одна и та же таска просто двигает выполнение корутины от одного авайта фьючера к другому авайту.
Отличные статьи. Продолжайте пожалуйста. Очень бы хотелось почитать статью про взаимодействие сервер + фреймворк (про реализацию ASGI)
Владимир, спасибо за комментарий и за идею для новой статьи. Встречайте https://habr.com/ru/articles/1003282/
Статья супер, спасибо!
Как устроены задачи (Task) в asyncio