【发布时间】:2019-07-01 18:15:08
【问题描述】:
我正在尝试使用 aiohttp 包编写一些异步 GET 请求,并且已经弄清楚了大部分内容,但我想知道处理失败(作为异常返回)时的标准方法是什么。
到目前为止我的代码的总体思路(经过反复试验,我遵循here 的方法):
import asyncio
import aiofiles
import aiohttp
from pathlib import Path
with open('urls.txt', 'r') as f:
urls = [s.rstrip() for s in f.readlines()]
async def fetch(session, url):
async with session.get(url) as response:
if response.status != 200:
response.raise_for_status()
data = await response.text()
# (Omitted: some more URL processing goes on here)
out_path = Path(f'out/')
if not out_path.is_dir():
out_path.mkdir()
fname = url.split("/")[-1]
async with aiofiles.open(out_path / f'{fname}.html', 'w+') as f:
await f.write(data)
async def fetch_all(urls, loop):
async with aiohttp.ClientSession(loop=loop) as session:
results = await asyncio.gather(*[fetch(session, url) for url in urls],
return_exceptions=True)
return results
if __name__ == '__main__':
loop = asyncio.get_event_loop()
results = loop.run_until_complete(fetch_all(urls, loop))
现在运行正常:
- 正如预期的那样,
results变量填充有None条目,其中对应的 URL [即在urls数组变量中的相同索引处,即在输入文件urls.txt]中的相同行号处被成功请求,并且相应的文件被写入磁盘。 - 这意味着我可以使用 results 变量来确定哪些 URL 不成功(
results中的那些条目不等于None)
我查看了一些使用各种异步 Python 包(aiohttp、aiofiles 和 asyncio)的不同指南,但我还没有看到处理这最后一步的标准方法。
- 是否应该在
await语句“完成”/“完成”之后重试发送 GET 请求? - ...或者重试发送 GET 请求是否应该在失败时由某种回调启动
- 错误看起来像这样:
(ClientConnectorError(111, "Connect call failed ('000.XXX.XXX.XXX', 443)")即在端口443上对IP 地址000.XXX.XXX.XXX的请求失败,可能是因为服务器有一些限制,我应该在重试之前等待超时。
- 错误看起来像这样:
- 我是否可以考虑设置某种限制,以批量处理请求而不是全部尝试?
- 尝试列表中的几百个(超过 500 个)URL 时,我收到了大约 40-60 个成功请求。
天真地,我期待 run_until_complete 以这样的方式处理这个问题,它会在成功请求所有 URL 后完成,但事实并非如此。
我以前没有使用过异步 Python 和会话/循环,所以如果能帮助我找到如何获取 results,我将不胜感激。如果我能提供更多信息来改进这个问题,请告诉我,谢谢!
【问题讨论】:
标签: python python-asyncio aiohttp