【问题标题】:Exception handling in Python TornadoPython Tornado 中的异常处理
【发布时间】:2011-09-25 22:42:30
【问题描述】:

我正在尝试以这种方式处理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,不,我无法抓住它:( .
  • 我记得在使用龙卷风的过程中发生了一些难以捕捉的异常。也许看看一些正在进行的问题......对不起,我有一段时间没有使用 Tornado......

标签: python exception-handling tornado


【解决方案1】:

根据Tornado documentation

如果在获取过程中发生错误,则给予回调的 HTTPResponse 具有包含请求期间遇到的异常的非 None 错误属性。 你可以调用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 模块了解如何过滤它。

【讨论】:

  • 具体来说,Tornado 将日志记录到根处理程序。因此,如果要抑制它们,则需要将处理程序/过滤器附加到根目录。
【解决方案2】:

我根本不知道 Tornado,但我看了一下,你根本无法以这种方式捕获异常。异常是在 _HTTPConnection() 的构造函数中生成的,并且该构造函数中的大部分代码已经被不同的堆栈上下文包装:

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

因此,基本上每当那里生成异常(在您的示例中为 gaierror),它已经被捕获并通过 self.cleanup 处理,进而生成 599 响应 AFAICT:

@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 和 cleaup,但它是龙卷风的内部代码。至于我应该有一些机制可以在自己的代码中捕获类似的异常。
  • 通过查看代码的结构方式,我认为没有办法不修补 Tornado。
猜你喜欢
  • 2021-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-11
  • 2011-06-23
  • 1970-01-01
相关资源
最近更新 更多