Asyncio返回协程对象而非结果问题咨询(CCXT异步脚本场景)
解决异步脚本返回协程对象而非结果的问题
嘿,我来帮你搞定这个异步编程的小坑!你遇到的问题其实是新手入门异步时最容易踩的误区——没有正确等待协程执行完成,导致拿到的是未运行的协程对象,而不是你想要的交易所价格数据。
核心原因拆解
你提到用了asyncio.gather(),但它本身也是个异步函数(协程),必须用await关键字等待它,才能让事件循环执行所有传入的子协程,并收集它们的返回值。如果直接调用gather()或者只创建了协程对象却没交给事件循环执行,你得到的必然是协程对象列表/协程对象,而非预期的结果。
另外你提到的警告,大概率是因为事件循环的用法过时了(比如用了get_event_loop()+run_until_complete()),Python 3.7+推荐用更简洁安全的asyncio.run()来管理事件循环,能直接避免这类警告。
错误代码示例(你可能踩的坑)
假设你的原代码是类似这样的:
import asyncio import aiohttp async def get_exchange_price(exchange): # 模拟从交易所API获取价格 async with aiohttp.ClientSession() as session: async with session.get(f"https://api.{exchange}.com/v1/price") as resp: return await resp.json() def main(): exchanges = ["binance", "coinbase", "kraken"] # 这里只创建了协程对象列表,没执行 coroutines = [get_exchange_price(ex) for ex in exchanges] # 调用gather但没await,返回的是gather的协程对象 results = asyncio.gather(*coroutines) print(results) # 输出类似 <_GatheringFuture pending> 或协程对象列表 if __name__ == "__main__": main()
修正后的正确代码
只需要改两个关键地方:
- 把
main()改成异步函数,在里面await asyncio.gather() - 用
asyncio.run()启动主协程,自动管理事件循环
import asyncio import aiohttp async def get_exchange_price(exchange): async with aiohttp.ClientSession() as session: async with session.get(f"https://api.{exchange}.com/v1/price") as resp: return await resp.json() async def main(): exchanges = ["binance", "coinbase", "kraken"] coroutines = [get_exchange_price(ex) for ex in exchanges] # 关键:用await等待gather执行完成,拿到结果列表 results = await asyncio.gather(*coroutines, return_exceptions=True) # return_exceptions=True:如果某个协程出错,会返回异常对象而非中断整个任务 print(results) # 现在输出实际的价格数据列表 if __name__ == "__main__": # Python 3.7+推荐用法,自动创建/关闭事件循环 asyncio.run(main())
额外提示
- 永远记住:异步函数调用(比如
get_exchange_price(ex))只会创建协程对象,不会立即执行,必须交给事件循环(比如通过await、asyncio.run()或loop.run_until_complete())才能运行。 - 如果需要处理个别交易所API请求失败的情况,
asyncio.gather()的return_exceptions=True参数非常有用,它会把异常作为结果返回,而不是让整个任务崩溃。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

