Обработка исключений в Python Tornado - PullRequest
5 голосов
/ 26 сентября 2011

Я пытаюсь обработать исключение, произошедшее в 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

Что я делаю не так?

Ответы [ 2 ]

9 голосов
/ 02 октября 2011

Согласно документации Tornado :

Если во время выборки возникает ошибка, HTTPResponse, переданный обратному вызову, имеет атрибут ошибки Non-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 , чтобы узнать, как его фильтровать.

3 голосов
/ 28 сентября 2011

Я вообще не знаю Торнадо, но я посмотрел, и вы просто не можете поймать исключения таким образом. Исключение генерируется в конструкторе _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,
                            ))

Не уверен, отвечает ли это на ваш вопрос.

...