Каковы все эти устаревшие параметры "l oop" в asyncio? - PullRequest
6 голосов
/ 20 февраля 2020

Многие функции в asyncio устарели loop параметров, которые планируется удалить в Python 3.10. Примеры включают as_completed(), sleep() и wait().

Я ищу некоторый исторический контекст по этим параметрам и их удаление.

  • Какие проблемы решил loop? Почему кто-то использовал это в первую очередь?
  • Что не так с loop? Почему его массово удаляют?
  • Что заменяет loop, теперь, когда его нет?

Ответы [ 2 ]

9 голосов
/ 20 февраля 2020

Какие проблемы решил loop? Почему кто-то использовал его в первую очередь?

До Python 3.6, asyncio.get_event_loop() не гарантировалось возвращение события l oop, которое выполняется в данный момент, когда вызывается из сопрограммы asyncio или обратного вызова. Он будет возвращать любое событие l oop, которое было предварительно установлено с помощью set_event_loop(some_loop), или событие, автоматически созданное asyncio. Но код syn c может легко создать другой l oop с another_loop = asyncio.new_event_loop() и раскрутить его с помощью another_loop.run_until_complete(some_coroutine()). В этом сценарии get_event_loop(), вызываемый внутри some_coroutine, и сопрограммы, которые он ожидает, вернут some_loop, а не another_loop. Такого рода вещи не возникали бы при случайном использовании asyncio, но это должно было быть учтено библиотеками asyn c, которые не могли предположить, что они выполняются при событии по умолчанию l oop. (Например, в тестах или в некоторых случаях использования потоков может потребоваться ускорить событие l oop, не нарушая глобальную настройку с помощью set_event_loop.) Библиотеки предложат явный аргумент loop, где вы могли бы передайте another_loop в вышеупомянутом случае, и который вы будете использовать всякий раз, когда l oop отличается от l oop, настроенного с помощью asyncio.set_event_loop().

Эта проблема будет исправлена в Python 3.6 и 3.5.3, где get_event_loop() был изменен, чтобы надежно возвращать текущий l oop при вызове изнутри, возвращая another_loop в вышеописанном сценарии. Python 3.7 дополнительно вводит get_running_loop(), который полностью игнорирует глобальные настройки и всегда возвращает текущее значение l oop, вызывая исключение, если не внутри него. См. эту ветку для исходного обсуждения.

Как только get_event_loop() стал надежным, другой проблемой была проблема производительности. Поскольку событие l oop было необходимо для некоторых очень часто используемых вызовов, особенно для call_soon, было просто более эффективно передавать и кэшировать объект l oop. Сама Асинсио сделала это, и многие библиотеки последовали их примеру. В итоге get_event_loop() был ускорен в C и больше не был узким местом.

Эти два изменения сделали аргументы loop избыточными.

Что было не так с loop? Почему оно удаляется массово?

Как и любая другая избыточность, она усложняет API и открывает возможности для ошибок. Код Asyn c должен почти никогда просто случайным образом связываться с другим l oop, и теперь, когда get_event_loop() и корректен, и быстр, нет причин не использовать его.

Кроме того, проходить l oop через все уровни абстракции типичного приложения просто утомительно. С появлением async / await в других языках стало ясно, что распространение глобального объекта вручную не является эргономичным c и не требуется от программистов.

Что заменяет loop, теперь что он пропал?

Просто используйте get_event_loop(), чтобы получить l oop, когда вам это нужно. В качестве альтернативы вы можете использовать get_running_loop(), чтобы утверждать, что al oop работает.

Необходимость доступа к событию l oop несколько снижена в Python 3.7, так как некоторые функции, которые ранее были только доступны как методы для l oop, такие как create_task, теперь доступны как автономные функции.

2 голосов
/ 20 февраля 2020

Параметр loop был способом передачи глобального события l oop. Новые реализации тех же функций больше не требуют, чтобы вы передавали глобальное событие l oop, вместо этого они просто запрашивают его там, где это необходимо.

Как следует из документации https://docs.python.org/3/library/asyncio-eventloop.html: " Разработчикам приложений обычно следует использовать высокоуровневые асинхронные функции, такие как asyncio.run (), и им редко требуется ссылаться на объект l oop или вызывать его методы. "

Устранение необходимости передать его в библиотечные функции в соответствии с этим принципом. L oop не заменяется, но его исчезновение просто означает, что вам больше не придется иметь дело с ним «вручную».

...