异步中所有这些不赞成使用的“循环”参数是什么?
其中的许多函数asyncio
均已弃用loop
参数,计划在Python
3.10中将其删除。实例包括as_completed()
,sleep()
,和wait()
。
我正在寻找有关这些参数及其删除的一些历史背景。
loop
解决了什么问题?为什么首先要使用它?- 怎么了
loop
?为什么将其大规模删除? - 什么取代了
loop
,现在它消失了?
-
loop
解决了什么问题?为什么首先要使用它?在Python
3.6之前,asyncio.get_event_loop()
从asyncio协程或回调调用时,不能保证返回当前正在运行的事件循环。它会返回先前使用设置的任何事件循环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时不会发生这种情况,但是必须由异步库解决,该库不能假定它们在默认事件循环下运行。(例如,在测试或某些涉及线程的用法中,您可能希望启动事件循环而不用打扰到全局设置set_event_loop
。)这些库将提供显式loop
参数,以供您another_loop
在上述情况下进行传递,以及只要正在运行的循环不同于用设置的循环,就可以使用asyncio.set_event_loop()
。此问题将在Python 3.6和3.5.3中修复,在Python
3.6和3.5.3中get_event_loop()
已进行了修改,可以可靠地返回运行循环(如果从内部调用),并another_loop
在上述情况下返回。Python
3.7将另外引入get_running_loop()
,它会完全忽略全局设置,并始终返回当前正在运行的循环,如果不在其中,则会引发异常。有关原始讨论,请参见此主题。一旦
get_event_loop()
变得可靠,另一个问题就是性能。由于某些非常频繁使用的调用需要事件循环call_soon
,因此,传递和缓存循环对象的效率更高。Asyncio本身就是这样做的,许多库也纷纷效仿。最后get_event_loop()
是用C加速和不再是一个瓶颈。这两个更改使
loop
参数变得多余。怎么了
loop
?为什么将其大规模删除?与其他任何冗余一样,它使API复杂化,并为出错提供了可能性。异步代码几乎 永远不
应该只是随机地与不同的循环通信,而现在这get_event_loop()
既正确又快速,没有理由不使用它。同样,将循环遍历典型应用程序的所有抽象层也很繁琐。随着async /
await在其他语言中成为主流,很明显,手动传播全局对象已不再符合人体工程学,并且程序员也不需要这样做。什么取代了
loop
,现在它消失了?只需
get_event_loop()
在需要时使用它即可获得循环。另外,您可以get_running_loop()
用来断言循环正在运行。在Python 3.7中,访问事件循环的需要有所减少,因为某些以前只能作为循环方法使用的函数(例如)
create_task
现在可以作为独立函数使用。