【问题标题】:Mix tornado.gen.coroutine with async/await?将 tornado.gen.coroutine 与 async/await 混合?
【发布时间】:2020-11-02 23:04:58
【问题描述】:

我需要更改以下遗留 tornado 代码以调用异步函数 async def my_async1(self)

class MyHandler(tornado.web.RequestHandler):
    @gen.coroutine
    def get(self, action):
        ....
        

它们可以混合吗?如何重构代码?

class MyHandler(tornado.web.RequestHandler):
    @gen.coroutine 
    async def get(self, action):
        ....
        await self.my_async() # ? 
     

我可以删除@gen.coroutine 并添加async 吗?它们完全一样吗?

【问题讨论】:

标签: python tornado


【解决方案1】:

是的,它们几乎是一样的。 @gen.coroutine 来自 Python 没有 async/await 关键字的过去。所以@gen.coroutine 用于将常规函数(或生成器)转换为异步生成器。

对于较新的 python 版本(3.5+),async/await 语法应优先于 @gen.coroutine

在转换函数时记住这些事情:

  1. 不要用@gen.coroutine 装饰async def 函数(就像您在第二个代码示例中所做的那样)。
  2. yield 关键字替换为 await 关键字。
  3. yield None 声明有效,但 await None 无效。
  4. 您可以yield 一个列表(例如yield [f1(), f2()]),但对于await,使用await gen.multi(f1(), f2())await asyncio.gather(f1(), f2())。 (感谢 Ben 提到这一点。)

【讨论】:

  • 奇怪的是,Python 3.5之前的代码还要导入tornado?由于gen.coroutine 处于龙卷风中。 BTW,你说几乎一样,如果不一样有什么区别?
  • @ca9163d9 @gen.coroutine 用于生成器(带有yield 语句),而async def 函数是实际的协程(带有await 语句)。否则,它们的工作原理几乎相同。
  • 有些事情的工作方式略有不同。例如,在@gen.coroutine 中,您可以使用yield [f1(), f2()] 来并行执行操作。在async def 中,您必须使用像await gen.multi(f1(), f2())await asyncio.gather(f1(), f2()) 这样的包装器对象
  • 轻微修改对我有用。而不是 await gen.multi(f1(), f2()),传入一个函数列表。看起来像这样:await gen.multi([f1(), f2()])
猜你喜欢
  • 2016-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-18
  • 2019-06-09
  • 2021-12-15
  • 2019-11-05
相关资源
最近更新 更多