我正在使用Tornado 2.4,我正在尝试集成异步调用。
假设我需要通过HTTP调用访问远程资源,所以我在tornado.web.RequestHandler
中创建了这个函数:
@tornado.web.asynchronous
def get(self, *args):
try:
self.remote_call()
return 'OK'
except Exception, e:
self.handle_exception(e)
@gen.engine
def remote_call(self):
http_client = httpclient.AsyncHTTPClient()
response = yield gen.Task(http_client.fetch, 'http://google.com')
self.process(response)
所以我的问题是,由于remote_call
正在产生Task
,它显然会退出remote_call
函数并继续get函数。然后当我的任务完成时,引擎将处理响应。
但是如果在self.process(response)
中发生了错误,那么除了之外它不会被捕获,因为这部分代码实际上并没有在这里被调用,而是在我无法控制的引擎内部。
所以我的问题是,我可以控制这个引擎吗?我可以处理错误,我可以要求在函数结束时执行某些特定任务吗?
我可以直接在这个函数中执行此操作
@tornado.web.asynchronous
def get(self, *args):
self.remote_call()
return 'OK'
@gen.engine
def remote_call(self):
http_client = httpclient.AsyncHTTPClient()
response = yield gen.Task(http_client.fetch, 'http://google.com')
try:
self.process(response)
except:
self.handle_exception(e)
但我想让句柄异常通用,而不是在我的每个Handler上复制粘贴。
那么我有办法访问Tornado的引擎吗? 请注意,我使用的是Tornado 2.4,但如果需要,我可以迁移到3.0。 感谢
答案 0 :(得分:4)
您可以通过get
@gen.engine
来self.remote_call
打电话来处理gen.Task
,yield
,然后@tornado.web.asynchronous
@gen.engine
def get(self, *args):
try:
yield gen.Task(self.remote_call)
except Exception, e:
self.handle_exception(e)
self.finish() # Make sure you call this when `get` is asynchronous.
@gen.engine
def remote_call(self):
http_client = httpclient.AsyncHTTPClient()
response = yield gen.Task(http_client.fetch, 'http://google.com')
self.process(response)
从那个:
get
这将允许您在remote_call
中处理异常,但您仍会看到gen.coroutine
中引发异常的追溯。
但是,我强烈建议您升级。 Tornado现在是4.0版本。使用3.0或更高版本,您可以使用gen.engine
代替web.asynchronous
和@gen.coroutine
def get(self, *args):
try:
yield self.remote_call()
except Exception, e:
self.handle_exception(e)
self.finish()
@gen.coroutine
def remote_call(self):
http_client = httpclient.AsyncHTTPClient()
response = yield http_client.fetch('http://google.com')
self.process(response)
:
coroutine
remote_call
正确处理get
中引发的任何异常的追溯,并允许您在{{1}}中处理它。
答案 1 :(得分:1)
好的,谢谢它有效。不过我必须这样做:
@tornado.web.asynchronous
@gen.engine
def get(self, *args):
try:
yield gen.Task(lambda cb: self.remote_call())
except Exception, e:
self.handle_exception(e)
self.finish() # Make sure you call this when `get` is asynchronous.
@gen.engine
def remote_call(self):
http_client = httpclient.AsyncHTTPClient()
response = yield gen.Task(http_client.fetch, 'http://google.com')
self.process(response)