我遇到 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中使用异步方法,并处理异常?
答案 0 :(得分:2)
作为一般规则,协同程序只能被其他协同程序正确调用,因此在覆盖像WebSocketHandler.open
这样的基类的方法时,除非该方法是协程或记录为“可能是协程”或者“可能会回归未来”,将其作为协程是不安全的。 WebSocketHandler.open
可能不是协程(从Tornado 4.1开始)。
您可以使用IOLoop.spawn_callback
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
完成之前调用。