asyncio入门疑问:获取函数返回值与控制代码执行顺序
解决asyncio中接收返回值与等待任务完成的问题
刚接触asyncio确实容易在同步异步的衔接上踩坑,我来帮你一步步搞定这两个问题~
1. 接收findIntersectingFeatures的返回结果
loop.run_in_executor()会返回一个协程对象,你需要用await关键字等待它执行完成,才能拿到真实的返回值并赋值给变量。结合你的代码场景,具体写法如下:
import json import requests import time import asyncio startTime = time.perf_counter() # 替换已废弃的time.clock() out_json = "UML10kmbuffer.json" intersections = [] # 假设你的findIntersectingFeatures是类似这样的同步查询函数 def findIntersectingFeatures(coords): # 模拟调用外部服务的逻辑 resp = requests.get(f"https://your-service-url.com/api/intersect?coords={coords}") return resp.json().get("matched_ids", []) # 假设返回ID列表 async def main(): loop = asyncio.get_running_loop() # 假设你有一组需要处理的坐标数据 coords_list = [[116, 39], [120, 31], [113, 23]] # 示例坐标 for coords in coords_list: # 用await等待任务完成,直接接收返回值 current_result = await loop.run_in_executor(None, findIntersectingFeatures, coords) intersections.extend(current_result) # 把结果存入全局列表 print(f"当前坐标处理完成,返回ID:{current_result}") if __name__ == "__main__": asyncio.run(main())
这里的核心是await loop.run_in_executor(...):它会暂停当前协程,直到同步函数在线程池里执行完毕,然后把函数的返回值赋值给current_result。
2. 让print语句在所有任务执行完成后再打印
你之前的print提前执行,是因为没有等待所有异步任务完成就触发了打印逻辑。如果想批量并行处理任务,然后统一打印最终结果,可以用asyncio.gather()来收集所有任务,等待全部完成后再执行print:
async def main(): loop = asyncio.get_running_loop() coords_list = [[116, 39], [120, 31], [113, 23]] # 先把所有异步任务收集到列表中 tasks = [loop.run_in_executor(None, findIntersectingFeatures, coords) for coords in coords_list] # 等待所有任务完成,一次性拿到所有结果 all_results = await asyncio.gather(*tasks) # 合并所有结果 for result in all_results: intersections.extend(result) # 所有任务都完成后,再执行打印 print(f"所有查询完成,总耗时:{time.perf_counter() - startTime:.2f}秒") print(f"匹配到的所有ID:{intersections}")
asyncio.gather()会阻塞当前协程,直到传入的所有任务(也就是每个run_in_executor的调用)全部执行完毕,所以后面的print语句一定会在所有任务结束后才触发。
另外补充个小细节:如果你的查询逻辑允许,也可以把同步的requests换成异步的aiohttp,这样代码会更贴合asyncio的原生异步风格,不过用run_in_executor兼容同步代码的方案完全没问题,适合新手过渡。
内容的提问来源于stack exchange,提问作者J. Skinner
相关产品推荐
相关产品推荐

