异步函数中的 While 循环抛出 StopIteration
While loop in async function throws StopIteration
我正在开发一个程序,它异步地向一个服务发送一堆请求。从现在开始我有了这个角色,那里只有请求和等待结果 (ok_function
)。现在我需要添加获得结果的部分,如果它是 202 等待一段时间并重试,因为它 return 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
- 因为响应是一个模拟object 这可能会触发 StopIteration
异常。 - https://docs.aiohttp.org/en/stable/client_reference.html
尽管如此,在您有有意义的回复时尝试获取 JSON 正文是正确的做法,因此尝试添加正确的 read
回复是没有意义的模拟。
我正在开发一个程序,它异步地向一个服务发送一堆请求。从现在开始我有了这个角色,那里只有请求和等待结果 (ok_function
)。现在我需要添加获得结果的部分,如果它是 202 等待一段时间并重试,因为它 return 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
- 因为响应是一个模拟object 这可能会触发 StopIteration
异常。 - https://docs.aiohttp.org/en/stable/client_reference.html
尽管如此,在您有有意义的回复时尝试获取 JSON 正文是正确的做法,因此尝试添加正确的 read
回复是没有意义的模拟。