Python Tornado中的异常处理

5

我试图以以下方式处理AsyncClient.fetch引发的异常:


from tornado.httpclient import AsyncHTTPClient
from tornado.httpclient import HTTPRequest
from tornado.stack_context import ExceptionStackContext
from tornado import ioloop

def handle_exc(*args):
    print('Exception occured')
    return True

def handle_request(response):
    print('Handle request')

http_client = AsyncHTTPClient()

with ExceptionStackContext(handle_exc):
    http_client.fetch('http://some123site.com', handle_request)

ioloop.IOLoop.instance().start()

并查看下一个输出:


WARNING:root:uncaught exception
Traceback (most recent call last):
  File "/home/crchemist/python-3.2/lib/python3.2/site-packages/tornado-2.0-py3.2.egg/tornado/simple_httpclient.py", line 259, in cleanup
    yield
  File "/home/crchemist/python-3.2/lib/python3.2/site-packages/tornado-2.0-py3.2.egg/tornado/simple_httpclient.py", line 162, in __init__
    0, 0)
socket.gaierror: [Errno -5] No address associated with hostname
Handle request


我做错了什么?

你能捕获这个异常吗?似乎异常没有被正确地引发。 - Glaslos
@Glaslos,不好意思,我没能抓住它 :( 。 - Mykola Kharechko
我记得在使用tornado的过程中发生了一些难以捕捉的异常。也许可以在一些正在进行的问题中查看... 抱歉,我已经有一段时间没有使用Tornado了... - Glaslos
2个回答

9
根据Tornado文档
如果在获取过程中出现错误,传递给回调函数的HTTPResponse有一个非None的error属性,其中包含请求期间遇到的异常。您可以调用response.rethrow()在回调函数中抛出异常(如果有的话)。
from tornado.httpclient import AsyncHTTPClient
from tornado.httpclient import HTTPRequest
from tornado.stack_context import ExceptionStackContext
from tornado import ioloop

import traceback

def handle_exc(*args):
    print('Exception occured')
    return True

def handle_request(response):
    if response.error is not None:
        with ExceptionStackContext(handle_exc):
            response.rethrow()
    else:
        print('Handle request')

http_client = AsyncHTTPClient()

http_client.fetch('http://some123site.com', handle_request)
http_client.fetch('http://google.com', handle_request)

ioloop.IOLoop.instance().start()

您在控制台看到的信息只是一个警告(通过logging.warning发送)。它是无害的,但如果真的困扰您,可以查看logging模块以了解如何过滤它。


2
具体来说,Tornado将日志记录到根处理程序。因此,如果您想要抑制它们,您需要将处理程序/过滤器附加到根。 - Nisan.H

3

我对 Tornado 一无所知,但是我看了一眼,你不能用那种方式捕获异常。异常是在 _HTTPConnection() 构造函数中生成的,而该构造函数中的大部分代码已经被另一个堆栈上下文包装起来:

    with stack_context.StackContext(self.cleanup):
        parsed = urlparse.urlsplit(_unicode(self.request.url))
        [...]

基本上,每当出现异常(例如您的示例中的gaierror)时,它已被捕获并通过self.cleanup处理,这将生成一个599响应。
@contextlib.contextmanager
def cleanup(self):
    try:
        yield
    except Exception, e:
        logging.warning("uncaught exception", exc_info=True)
        self._run_callback(HTTPResponse(self.request, 599, error=e,
                            request_time=time.time() - self.start_time,
                            ))

不确定这是否回答了你的问题。


谢谢。我也在看_Connection和清理,但这是tornado的内部代码。对我来说,应该有一些机制可以在自己的代码中捕获这样的异常。 - Mykola Kharechko
通过查看代码的结构,我认为没有不修补Tornado的方法。 - Giovanni Bajo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接