我正在使用uvloop
websockets
作为
import uvloop
coro = websockets.serve(handler, host, port) # creates new server
loop = uvloop.new_event_loop()
loop.create_task(coro)
loop.run_forever()
它工作正常,我只是想知道如果不将全局asyncio
政策设置为uvloop
,我是否会遇到一些意外问题。据我所知,不设置全局策略应该有效,只要没有任何东西不使用全局asyncio
方法,而是直接使用传递的事件循环。这是对的吗?
答案 0 :(得分:3)
如果要在不使用asyncio.set_event_loop(loop)
的情况下使用自定义事件循环,则必须将循环作为参数传递给每个相关的asyncio协同程序或对象,例如:
await asyncio.sleep(1, loop=loop)
或
fut = asyncio.Future(loop=loop)
您可能会注意到asyncio
模块中的任何协程/对象都可能接受此参数。
同样的事情也适用于websockets
库may see来自它的源代码。所以你需要写:
loop = uvloop.new_event_loop()
coro = websockets.serve(handler, host, port, loop=loop) # pass loop as param
如果您未能将事件循环作为这样的参数传递,那么您的程序无法保证正常工作。
虽然理论上你可以在不改变政策的情况下使用某些事件循环,但我发现它非常不舒服。
你必须在几乎所有地方写loop=loop
,这很烦人
不保证某些第三方允许您通过
循环作为参数并且不会使用asyncio.get_event_loop()
基于此,我建议您重新考虑您的决定并使用全局事件循环。
我知道可能感觉到"不正常"使用全局事件循环,但是"对"方式是传递循环,因为param在实践中的每个地方都更糟糕(在我看来)。
答案 1 :(得分:3)
asyncio中有三个主要的全局对象:
在asyncio中获取当前上下文的所有尝试都通过单个函数asyncio.get_event_loop。
要记住的一件事是since Python 3.6(和Python 3.5.3+),get_event_loop
有一个特定的行为:
import uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
loop = asyncio.get_event_loop()
loop.run_forever()
此政策是uvloop政策。 get_event_loop
返回的循环是一个uvloop,它被设置为该线程的默认循环。当此循环运行时,它将被注册为运行循环。
在此示例中,在此线程中的任何位置调用get_event_loop()
将返回正确的循环。
import uvloop
loop = uvloop.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_forever()
此处策略仍然是默认策略。 new_event_loop
返回的循环是一个uvloop,它使用asyncio.set_event_loop
显式设置为该线程的默认循环。当此循环运行时,它将被注册为运行循环。
在此示例中,在此线程中的任何位置调用get_event_loop()
将返回正确的循环。
import uvloop
loop = uvloop.new_event_loop()
loop.run_forever()
此处策略仍然是默认策略。 new_event_loop
返回的循环是一个uvloop,但它没有被设置为该线程的默认循环。当此循环运行时,它将被注册为运行循环。
在此示例中,在协程中调用get_event_loop()
会返回正确的循环(正在运行的uvloop)。但是在协程外调用get_event_loop()
将导致新的标准asyncio循环,设置为该线程的默认循环。
所以前两种方法都没问题,但第三种方法是不鼓励的。