asyncio 中所有这些已弃用的 "loop" 参数是什么?

What are all these deprecated "loop" parameters in asyncio?

asyncio 中的许多函数已弃用 loop 参数,计划在 Python 3.10 中删除。示例包括 as_completed(), sleep(), and wait().

我正在寻找有关这些参数及其删除的一些历史背景。

loop 参数是传递全局事件循环的方式。相同功能的新实现不再需要您传递全局事件循环,它们只是在需要的地方请求它。

如文档所示 https://docs.python.org/3/library/asyncio-eventloop.html:"Application developers should typically use the high-level asyncio functions, such as asyncio.run(), and should rarely need to reference the loop object or call its methods."

消除将其传递给库函数的需要符合该原则。循环没有被替换,但它的消失仅仅意味着你不再需要处理它'manually'.

What problems did loop solve? Why would one have used it in the first place?

在 Python 3.6 之前,当从 asyncio 协程或回调调用时,asyncio.get_event_loop() 不能保证 return 当前 运行 事件循环。它会 return 之前使用 set_event_loop(some_loop) 设置的任何事件循环,或者由 asyncio 自动创建的事件循环。但是同步代码可以很容易地使用 another_loop = asyncio.new_event_loop() 创建一个不同的循环并使用 another_loop.run_until_complete(some_coroutine()) 将其旋转起来。在这种情况下,get_event_loop()some_coroutine 内部调用,它等待的协程将 return some_loop 而不是 another_loop。这种事情在随便使用 asyncio 时不会发生,但它必须由异步库考虑,因为它们不能假设它们在默认事件循环下是 运行。 (例如,在测试中或涉及线程的某些用法中,人们可能希望在不使用 set_event_loop 干扰全局设置的情况下启动事件循环。)库会提供显式的 loop 参数d 在上述情况下传递 another_loop,只要 运行 循环与 asyncio.set_event_loop().

设置的循环不同,您就会使用它

这个问题将 fixed in Python 3.6 and 3.5.3, where get_event_loop() was modified to reliably return the running loop if called from inside one, returning another_loop in the above scenario. Python 3.7 would additionally introduced get_running_loop() which completely ignores the global setting and always returns the currently running loop, raising an exception if not inside one. See this thread 用于原始讨论。

一旦get_event_loop()变得可靠,另一个问题就是性能。由于一些非常频繁使用的调用需要事件循环,尤其是 call_soon, it was simply more efficient to pass around and cache the loop object. Asyncio itself did that, and many libraries followed suit. Eventually get_event_loop() was accelerated in C 并且不再是瓶颈。

这两项更改使 loop 参数变得多余。

What was wrong with loop? Why is it being removed en masse?

与任何其他冗余一样,它使 API 复杂化并导致出现错误的可能性。异步代码应该几乎 never 只是随机地与不同的循环通信,现在 get_event_loop() 既正确又快速,没有理由不使用它。

此外,让循环遍历典型应用程序的所有抽象层非常乏味。随着 async/await 成为其他语言的主流,很明显手动传播全局对象不符合人体工程学,不应要求程序员。

What replaces loop, now that it's gone?

只需在需要时使用get_event_loop()即可获得循环。或者,您可以使用 get_running_loop() 断言循环是 运行.

在 Python 3.7 中,访问事件循环的需求有所减少,因为一些以前只能作为循环方法使用的函数,例如 create_task,现在可以作为标准函数使用- 独立功能。