首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在不设置全局策略的情况下使用替代事件循环

在不设置全局策略的情况下使用替代事件循环
EN

Stack Overflow用户
提问于 2017-05-16 11:23:09
回答 2查看 1.6K关注 0票数 4

我使用uvloopwebsockets作为

代码语言:javascript
复制
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方法,而是直接使用传递下来的事件循环即可。对吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-05-16 12:05:57

异步中有三个主要的全局对象:

  • 策略(对所有线程通用)
  • 默认循环(特定于当前线程)
  • 正在运行的循环(特定于当前线程)

在异步中获取当前上下文的所有尝试都经过一个函数循环播放

需要记住的一件事是,自Python 3.6以来 (和Python 3.5.3+),get_event_loop有一个特定的行为:

  • 如果在循环运行时调用它(例如,在coroutine中),则返回正在运行的循环。
  • 否则,策略将返回默认循环。

示例1:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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:

代码语言:javascript
复制
import uvloop
loop = uvloop.new_event_loop()
loop.run_forever()

在这里,策略仍然是默认策略。new_event_loop返回的循环是uvloop,但它不是这个线程的默认循环。当这个循环运行时,它被注册为正在运行的循环。

在本例中,在coroutine中调用get_event_loop()将返回右循环(正在运行的uvloop)。但是,在coroutine之外调用get_event_loop()将产生一个新的标准异步循环,该循环设置为该线程的默认循环。

因此,前两种方法都很好,但是第三种方法是不鼓励的。

票数 6
EN

Stack Overflow用户

发布于 2017-05-16 12:05:44

应该将自定义事件循环作为param传递。

如果您不想使用自定义事件循环而不使用asyncio.set_event_loop(loop),则必须将循环作为param传递给每个相关的异步协同或对象,例如:

代码语言:javascript
复制
await asyncio.sleep(1, loop=loop)

代码语言:javascript
复制
fut = asyncio.Future(loop=loop)

您可能会注意到,asyncio模块中的任何coroutine/object都可能接受这个param。

同样的东西也应用到websockets库中,就像您从它的源代码中获得的可以看到一样。所以你需要写:

代码语言:javascript
复制
loop = uvloop.new_event_loop()
coro = websockets.serve(handler, host, port, loop=loop)  # pass loop as param

如果您不像这样通过事件循环,则不能保证您的程序能够正常工作。

可能,但不舒服

虽然理论上您可以在不改变策略的情况下使用一些事件循环,但我发现这非常不舒服。

  • 你几乎在任何地方都要写loop=loop,这很烦人
  • 不能保证某些第三方允许您以param形式传递循环,而不只是使用asyncio.get_event_loop()

在此基础上,我建议您重新考虑您的决定,并使用全局事件循环。

我知道使用全局事件循环可能会感到“不对”,但“正确”的方式是传递循环,因为在实践中,处处都是param (我认为)。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44000136

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档