Python Tornado gen.engine异常处理

时间:2014-08-06 18:25:07

标签: python exception tornado

我正在使用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。 感谢

2 个答案:

答案 0 :(得分:4)

您可以通过get @gen.engineself.remote_call打电话来处理gen.Taskyield,然后@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)