我使用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方法,而是直接使用传递下来的事件循环即可。对吗?
发布于 2017-05-16 12:05:57
异步中有三个主要的全局对象:
在异步中获取当前上下文的所有尝试都经过一个函数循环播放。
需要记住的一件事是,自Python 3.6以来 (和Python 3.5.3+),get_event_loop有一个特定的行为:
示例1:
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()都会返回右循环。
示例2:
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()都会返回右循环。
例3:
import uvloop
loop = uvloop.new_event_loop()
loop.run_forever()在这里,策略仍然是默认策略。new_event_loop返回的循环是uvloop,但它不是这个线程的默认循环。当这个循环运行时,它被注册为正在运行的循环。
在本例中,在coroutine中调用get_event_loop()将返回右循环(正在运行的uvloop)。但是,在coroutine之外调用get_event_loop()将产生一个新的标准异步循环,该循环设置为该线程的默认循环。
因此,前两种方法都很好,但是第三种方法是不鼓励的。
发布于 2017-05-16 12:05:44
应该将自定义事件循环作为param传递。
如果您不想使用自定义事件循环而不使用asyncio.set_event_loop(loop),则必须将循环作为param传递给每个相关的异步协同或对象,例如:
await asyncio.sleep(1, loop=loop)或
fut = asyncio.Future(loop=loop)您可能会注意到,asyncio模块中的任何coroutine/object都可能接受这个param。
同样的东西也应用到websockets库中,就像您从它的源代码中获得的可以看到一样。所以你需要写:
loop = uvloop.new_event_loop()
coro = websockets.serve(handler, host, port, loop=loop) # pass loop as param如果您不像这样通过事件循环,则不能保证您的程序能够正常工作。
可能,但不舒服
虽然理论上您可以在不改变策略的情况下使用一些事件循环,但我发现这非常不舒服。
loop=loop,这很烦人asyncio.get_event_loop()在此基础上,我建议您重新考虑您的决定,并使用全局事件循环。
我知道使用全局事件循环可能会感到“不对”,但“正确”的方式是传递循环,因为在实践中,处处都是param (我认为)。
https://stackoverflow.com/questions/44000136
复制相似问题