【问题标题】:Tornado: catching exceptions inside asynchronous openTornado:在异步打开中捕获异常
【发布时间】:2015-03-03 18:43:19
【问题描述】:

我对 WebSocketHandler 的方法 open 有问题。 我用 gen.coroutine 包装它,以便在内部使用异步调用(访问 redis)。但是还有一个问题,open 中的任何错误都不会被捕获。

例子:

@gen.coroutine
def open(self):
    t = 8/0
    self._connection_id = yield self._generate_connection_id()
    self.write_message('...')

方法 open 在 WebSocketProtocol._run_callback 内部调用:

def _run_callback(self, callback, *args, **kwargs):
    try:
        callback(*args, **kwargs)
    except Exception:
        app_log.error("Uncaught exception in %s",
                      self.request.path, exc_info=True)
        self._abort()

这个方法没有任何装饰器,所以方法打开返回future并且这个异常没有被处理。

那么如何在 open 中使用 async 方法,并处理异常?

【问题讨论】:

    标签: asynchronous websocket tornado coroutine


    【解决方案1】:

    作为一般规则,协程只能被其他协程正确调用,因此当覆盖 WebSocketHandler.open 等基类的方法时,除非该方法是协程或记录为“可能是协程”或“可能返回一个未来”,让它成为一个协程是不安全的。 WebSocketHandler.open 可能不是协程(从 Tornado 4.1 开始)。

    你可以使用IOLoop.spawn_callback从 open() 生成一个协程:

    def open(self):
        IOLoop.current().spawn_callback(self.async_open)
    
    @gen.coroutine
    def async_open(self):
        #...
    

    在async_open 中,您可以像往常一样使用try/except 处理错误(spawn_callback 还会为您记录异常作为最后的手段)。您还有责任处理async_open 和on_message 或on_close 之间可能出现的任何时间问题,因为这些方法可能在async_open 完成之前被调用。

    【讨论】:

      猜你喜欢
      • 2012-08-14
      • 1970-01-01
      • 2011-08-12
      • 2013-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多