在早些时候的问题中,aiohttp
的一位作者提出了一种使用 Python 3.5 中的新 async with
语法来获取多个 URL 的方法。
import aiohttp
import asyncio
async def fetch(session, url):
with aiohttp.Timeout(10):
async with session.get(url) as response:
return await response.text()
async def fetch_all(session, urls, loop):
results = await asyncio.wait([loop.create_task(fetch(session, url))
for url in urls])
return results
if __name__ == '__main__':
loop = asyncio.get_event_loop()
# breaks because of the first url
urls = ['http://SDFKHSKHGKLHSKLJHGSDFKSJH.com',
'http://google.com',
'http://twitter.com']
with aiohttp.ClientSession(loop=loop) as session:
the_results = loop.run_until_complete(
fetch_all(session, urls, loop))
# do something with the the_results
然而,当session.get(url)
请求之一失败时(如上述因http://SDFKHSKHGKLHSKLJHGSDFKSJH.com
),错误未被处理,整个程序就会崩溃。
我寻找了关于session.get(url)
结果插入测试的方法,例如寻找一个 try ... except ...
的地方,或者一个 if response.status!= 200:
的地方,但我只是不明白如何使用async with
,await
和各种对象。
由于async with
仍然非常新,因此没有很多示例。如果一个asyncio
专家能够展示如何做到这一点,那将对许多人非常有帮助。毕竟,大多数人想要使用asyncio
测试的第一件事情之一就是同时获取多个资源。
目标
目标是我们可以检查the_results
并快速地查看以下内容:
- 此URL失败了(以及原因:状态代码,也许是异常名称);或者
- 此URL有效,并且这里有一个有用的响应对象。
asyncio.gather
后立即迭代结果,那么在fetch
列表上使用asyncio.as_completed
是否更好呢?这样你就可以立即迭代已完成的任务,而不必等待所有任务都完成。 - dalanmiller