【问题标题】:Exception handling for parallel fetch requests并行获取请求的异常处理
【发布时间】:2016-02-22 17:45:28
【问题描述】:

我有以下代码:

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

我不能保证给定的网址是有效的。我希望能够使用异常来验证 url。如何判断在捕获的异常中哪些 url(s) 失败?

另外,如果一次提取失败(比如第一次),其余的提取似乎会中断?有没有办法防止这种情况?或者有没有更好的方法在实际获取之前检查 URL 是否可以获取?有没有更好的模式。基本上,我想并行获取所有 URL,并知道哪一个可能会失败。

【问题讨论】:

    标签: tornado


    【解决方案1】:

    最简单的解决方案是将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")
    

    【讨论】:

      【解决方案2】:

      我想过做以下事情:

            @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 修饰过的函数的一部分,这会造成问题吗?

      【讨论】:

        【解决方案3】:

        乍一看,您答案中的方法还可以,甚至比 Tornado 的方法更优雅。 WaiterIterator 是处理这种情况的“参考”解决方案。我将 Tornado 的文档示例包装为:

        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 一起工作就像魅力一样。

        【讨论】:

        • 谢谢!我不知道;)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-04
        • 2014-08-05
        • 1970-01-01
        • 1970-01-01
        • 2020-06-24
        相关资源
        最近更新 更多