Какие проблемы решил 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
, теперь доступны как автономные функции.