首页 > 解决方案 > 使用 asyncio.gather(func1(),func2()) 时数据被覆盖

问题描述

我从 API 请求数据。

async def get_data(request_details):
    value1, value2 = await api.get_values(request_details)
    ..some extra calculations
    return value1, value2

async def routine1():
    val1, val2 = await get_data(request_details1)
    ...do something with val1, val2

async def routine2():
    val1, val2 = await get_data(request_details2)
    ...do something with val1, val2


async def main():
    await asyncio.gather(routine1(),routine2())

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    loop.close()

我需要启动这两个例程,以便他们可以异步地做他们的事情。会发生什么,我得到了 val1, val2 由 get_data() 函数返回给我,它们是相同的。它们对于routine1() 是正确的,但对于routine2() 它们与routine1() 相同。

如果我将 main() 中的例程调用从使用 asyncio.gather() 更改为

await routine1()
await routine2()

然后它们不会异步启动,但我确实在两者中都得到了正确的 val1,val2。我在这里想念什么?为什么我的数据会被覆盖?

标签: pythonasynchronouspython-asyncio

解决方案


因为它是正确的 -api.get_values你正在调用的机会不是保持每个异步调用独立并且它们返回相同的值。除了你说哪个 API 和我们查看它的代码之外,没有办法正确回答这个问题。

由于这是该 API 中的一个问题,如果它提供同步调用,这可能是一种解决方法 - 然后,在您的 api 调用内部get_data,而不是等待损坏api.get_values,您可以使用loop.run_in_executor单独调用 api 的同步版本线。跳转 api 是 thread_safe,也就是说,它应该可以工作:

async def get_data(request_details):
    loop = asyncio.get_event_loop()
    value1, value2 = await loop.run_in_executor(api.get_values_sync, request_details)
    ..some extra calculations
    return value1, value2

推荐阅读