【发布时间】:2021-06-05 15:29:02
【问题描述】:
函数make_request 向API 发出http 请求。而且我每秒最多只能发出 3 个请求。
我做过类似的事情
coroutines = [make_request(...) for ... in ...]
tasks = []
for coroutine in coroutines:
tasks.append(asyncio.create_task(coroutine))
await asyncio.sleep(1 / 3)
responses = asyncio.gather(*tasks)
但我每小时发出的请求也不能超过 1000 个。 (也许,我可以延迟3600 / 1000。)如果互联网连接丢失怎么办?我应该尝试再次提出请求。
我可以这样包装make_request:
async def try_make_request(...):
while True:
try:
return await make_request(...)
exception APIError as err:
logging.exception(...)
在这种情况下,每秒可能会发出超过 3 个请求。
我找到了that 解决方案,但我不确定这是不是最好的解决方案
pending = []
coroutines = [...]
for coroutine in coroutines:
pending.append(asyncio.create_task(coroutine))
await asyncio.sleep(1 / 3)
result = []
while True:
finished, pending = await asyncio.wait(
pending, return_when=asyncio.FIRST_EXCEPTION
)
for task in finished:
exc = task.exception()
if isinstance(exc, APIError) and exc.code == 29:
pending.add(task.get_coro()) # since python 3.8
if exc:
logging.exception(...)
else:
result.append(task.result())
if not pending:
break
【问题讨论】:
-
使用
task.get_coro()的解决方案看起来很奇怪,它甚至可以工作吗?如果协程已经引发并因此完成,我认为您不能直接等待它,也不能通过新任务等待它。
标签: python python-3.x asynchronous async-await python-asyncio