我有以下代码:
try:
responses = yield [httpClient.fetch(url) for url in urls]
except (HTTPError, IOError, ValueError) as e:
print("caught")
我无法保证给出的网址有效。我希望能够使用该例外来验证网址。如何判断哪个URL在捕获的异常中失败?
此外,如果一次提取失败(比如说第一次),它看起来好像是其他提取中断了吗?有办法防止这种情况吗?或者是否有更好的方法来检查在实际获取之前可以获取URL?对此有更好的模式吗?基本上我想并行获取所有URL并知道哪一个可能失败。
答案 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
的魅力一样。