asyncio 中所有这些已弃用的“循环”参数是啥?

Posted

技术标签:

【中文标题】asyncio 中所有这些已弃用的“循环”参数是啥?【英文标题】:What are all these deprecated "loop" parameters in asyncio?asyncio 中所有这些已弃用的“循环”参数是什么? 【发布时间】:2020-02-20 03:11:52 【问题描述】:

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

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

loop 解决了哪些问题?为什么一开始会使用它? loop 出了什么问题?为什么会被大量删除? loop 消失了,用什么代替?

【问题讨论】:

您的问题措辞不同,但在此回答 ***.com/questions/40340493/… - 您不再需要/获得通过特定事件循环。 我不觉得我的“发生了什么以及为什么”的问题在那里得到了回答。我基本上阅读了另一个问题,它的 cmets 和它的答案,告诉我该怎么做,没有太多的理由。 (基本上,我首先要重申的弃用警告。) 该答案中链接的文章从字面上回答了您的问题mail.python.org/pipermail/async-sig/2016-November/000171.html - 发生了什么 = 全局事件循环导致问题,为什么会发生 = 糟糕的设计决策,出了什么问题 = 循环是为了传递全局循环,取代它的东西 = 什么都没有,它仍然存在,但你不再需要传递它(解决许多问题),如果你需要它,你可以将它作为 current_event_loop() @Grismar 我的问题的答案很可能在那篇文章中,但它不在链接到那篇文章的 Stack Overflow 答案中!我也不希望它是 - 这两个问题谈论的是同一件事,但我所问的是不同的。 【参考方案1】:

loop 解决了哪些问题?为什么一开始会使用它?

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

此问题在 Python 3.6 和 3.5.3 中为 fixed,其中 get_event_loop() 已修改为在从内部调用时可靠地返回运行循环,在上述情况下返回 another_loop。 Python 3.7 将另外引入get_running_loop(),它完全忽略全局设置并始终返回当前正在运行的循环,如果不在循环内部,则会引发异常。有关原始讨论,请参阅this thread。

一旦get_event_loop() 变得可靠,另一个问题就是性能问题。由于一些非常频繁使用的调用需要事件循环,尤其是call_soon,因此传递和缓存循环对象更有效。 Asyncio 本身就是这样做的,许多库也纷纷效仿。最终get_event_loop() 变成了accelerated in C,不再是瓶颈。

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

loop 出了什么问题?为什么会被大量删除?

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

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

loop 已经不存在了,用什么替代它?

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

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

【讨论】:

【参考方案2】:

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

正如文档所建议的 https://docs.python.org/3/library/asyncio-eventloop.html:“应用程序开发人员通常应该使用高级 asyncio 函数,例如 asyncio.run(),并且应该很少需要引用循环对象或调用其方法。”

消除将其传递给库函数的需要符合该原则。循环不会被替换,但它的消失仅仅意味着您不再需要“手动”处理它。

【讨论】:

以上是关于asyncio 中所有这些已弃用的“循环”参数是啥?的主要内容,如果未能解决你的问题,请参考以下文章

图像中已弃用的 Notification 类的替代方法是啥?

管理 Firebase 安装实施的截止日期是啥时候?移动应用中已弃用的 Firebase 安装 ID 有啥影响?

已弃用的 Hibernate.createClob(Reader reader, int length) 的替代方法是啥

已弃用的 OpenGL 功能

如何隐藏zend framework2已弃用的消息

如何手动更新已弃用的类型包