async函数中的While循环引发StopIteration



我正在开发一个程序,它异步地向一个服务发送一堆请求。从现在起,我有了这个角色,那里只有请求和等待结果(ok_function(。现在我需要添加得到结果的部分,如果是202,请等待一段时间,然后重试,因为它返回200。

它看起来像这样:

async def async_make_requests(parsed_data, url):
async with aiohttp.ClientSession() as session:
tasks = []
for x, y in parsed_data.items():
if something:
tasks.append(
asyncio.ensure_future(
function_with_sleep(
session, x, y,
)
)
)
else:
tasks.append(
asyncio.ensure_future(
ok_function(
session, x, y,
)
)
)   
results = await asyncio.gather(*tasks)
return results
async def function_with_sleep(session, x, y):
not_processed_yet = True
while not_processed_yet:
async with session.get(x, data=y) as r:
response = await r.json()
status_code = r.status
if status_code == 202:
await asyncio.sleep(10)
else:
not_processed_yet = False
...
async def ok_function(session, x, y)
async with session.post(x, data=y) as r:
response = await r.json()
status_code = r.status
...

在使用进行测试时

resp_processing = MockResponse(202, response)
resp_ok = MockResponse(200, response)
mocker.patch("aiohttp.ClientSession.get", side_effect=[resp_processing, resp_ok])
return_value = await async_make_requests(parsed_data, "anyurl")

我得到:

results = await asyncio.gather(*tasks) RuntimeError: coroutine raised StopIteration

ok_function工作正常,function_with_sleep只有在不重复且不休眠的情况下工作正常。

我不知道这里出了什么问题。

代码看起来是正确的——尽管您也没有说明session属于哪个http框架:如果r.json在发出的请求中没有json主体时引发错误,则会传播此错误-如果是StopIteration,则会破坏asyncIO.gather,如前所述(否则,将在相应的任务中设置任务异常(。

尝试在获得200状态代码后立即调用await r.json(),而不是在测试状态代码之前。如果你声称的行为确实是由你在问题中粘贴的代码引起的,这应该会解决它

事实上,你似乎在使用aiohttp,或者基于它的东西:如果请求对象中没有正文,它将在响应中调用.read-因为响应是一个mock对象,这可能会触发StopIteration异常。-https://docs.aiohttp.org/en/stable/client_reference.html

尽管如此,当您有一个有意义的响应时尝试获取JSON主体是正确的做法,因此尝试向mock添加正确的read响应是没有意义的。

最新更新