Tornado:在异步打开中捕获异常

时间:2015-03-03 18:43:20

标签: asynchronous websocket tornado coroutine

我遇到 WebSocketHandler 的方法 open 的问题。 我用 gen.coroutine 包装它以在内部使用异步调用(访问redis)。但是有另外一个问题,打开的任何错误都没有发现。

示例:

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

方法打开是在 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()

此方法没有任何装饰器,因此方法打开返回将来并且不处理此异常。

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

1 个答案:

答案 0 :(得分:2)

作为一般规则,协同程序只能被其他协同程序正确调用,因此在覆盖像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_openon_messageon_close之间可能出现的任何时间问题也是您的责任,因为这些方法可能会在async_open完成之前调用。