【问题标题】:tornado, make on_finish() asynchronous龙卷风,使 on_finish() 异步
【发布时间】:2018-12-24 19:27:21
【问题描述】:

覆盖方法 on_finish()。 用.gen.coroutine 装饰这个方法,使其异步,它工作。

@gen.coroutine
def on_finish(self):
    print("==========on_finish==============")

但使用async def 使其异步,它失败了。

async def on_finish(self):
    print("==========on_finish==============")

# RuntimeWarning: coroutine 'BaseHandler.on_finish' was never awaited

self.on_finish()

为什么我不能使用async def 使其异步?

【问题讨论】:

  • 我想是因为tornado runs on_finish() synchronously。您的第一个示例没有工作,它只是没有引发任何错误,因为它在语法上是正确的并且默默地失败了。我在add_callback() 电话中看到了可能的解决方法。
  • 是的,Fian 是对的。 Tornado 不支持将 on_finish 设为异步函数。但是你想做什么?为什么要让它异步?
  • 我使用 TorMySQL 异步连接 mysql。在 prepare() 函数中,我得到一个 db.conn(),我想在 on_finish() 函数中自动关闭连接。函数 db.conn.close() 必须是异步的
  • @Lvxiuquan 就像上面Fian已经指出的那样,您可以使用add_callback()方法安排关闭连接。 Tornado 将异步运行它。如果你愿意,我可以发布示例代码。
  • @xyres 不要打扰。我明白了,谢谢。

标签: asynchronous tornado coroutine


【解决方案1】:

协程与常规函数有不同的接口。覆盖方法时,应根据其文档将其设为协程(或不设为协程)。 Tornado 中所有可能是协程的可覆盖方法在他们的文档中都有说明,on_finish 不是其中之一。

如果你在超类不期望的情况下使用协程会发生什么?如您所见,这取决于协程的类型。 @gen.coroutine 是“自启动”,所以协程将启动,但没有任何东西会等待它完成,如果它引发异常,则无处可捕获该异常(因此它只会被IOL 循环)。 async def 协程不会自动启动,这是必须 await 它们,所以如果你在调用者不期望协程的地方使用协程,什么都不会发生。

如果您需要使用不允许的方法中的协程,您需要决定谁将等待协程并处理其异常。如果您不需要捕获异常并且可以将它们留给日志,您可以使用IOLoop.add_callback 明确将此责任赋予 IOLoop:

def on_finish(self):
    IOLoop.current().add_callback(self.on_finish_async)

async def on_finish_async(self):
    ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多