并行提取请求的异常处理

时间:2016-02-22 17:45:29

标签: tornado

我有以下代码:

  try:
     responses = yield [httpClient.fetch(url) for url in urls]
  except (HTTPError, IOError, ValueError) as e:
     print("caught")

我无法保证给出的网址有效。我希望能够使用该例外来验证网址。如何判断哪个URL在捕获的异常中失败?

此外,如果一次提取失败(比如说第一次),它看起来好像是其他提取中断了吗?有办法防止这种情况吗?或者是否有更好的方法来检查在实际获取之前可以获取URL?对此有更好的模式吗?基本上我想并行获取所有URL并知道哪一个可能失败。

3 个答案:

答案 0 :(得分:5)

最简单的解决方案是将raise_error=False传递给fetch()。这将始终为您提供回复,您将能够检查response.error或使用response.rethrow()

responses = yield [httpClient.fetch(url, raise_error=False) for url in urls]
for url, resp in zip(urls, responses):
    try:
        resp.rethrow()
        print("succeeded")
    except (HTTPError, IOError, ValueError) as e:
        print("caught")

答案 1 :(得分:1)

我考虑过做以下事情:

      @tornado.gen.coroutine
      def wrap(httpClient,url):
         try:
            response=yield httpClient.fetch(url)
         except (HTTPError, IOError, ValueError,StopIteration) as e:
            return e
         return response



      httpClient=AsyncHTTPClient()
      responses=yield [wrap(httpClient,url) for url in urls]

有更好或更优雅的方式吗?这也是已经由@ tornado.gen.coroutine装饰的函数的一部分会产生问题吗?

答案 2 :(得分:1)

你的答案中的方法是好的,乍一看比Tornado的更优雅。 WaiterIterator是"参考"处理这种情况的解决方案。我把Tornado的doc示例包装成:

from tornado.ioloop import IOLoop
from tornado.gen import coroutine, WaitIterator
from tornado.httpclient import AsyncHTTPClient, HTTPError

@coroutine
def multi_exc_safe(futures):
    multi = {}
    wait_iterator = WaitIterator(*futures)
    while not wait_iterator.done():
        try:
            res = yield wait_iterator.next()
            multi[wait_iterator.current_index] = res
        except (HTTPError, IOError, ValueError,StopIteration) as e:
            multi[wait_iterator.current_index] = e
    return multi

@coroutine
def main():
    urls = [
        'http://google.com',
        'http://nnaadswqeweqw342.comm',
    ]
    httpclient = AsyncHTTPClient()
    responses = yield multi_exc_safe([httpclient.fetch(url) for url in urls])
    print(responses)

IOLoop.instance().run_sync(main)

关于WaiterIterator的酷事(可能与你的问题无关)是,它是一个迭代器:)。它允许尽快得到回复,并且与async for的魅力一样。