python-binance结合asyncio多任务调用Binance API遇阻塞问题求助
解决python-binance异步任务卡住问题
1. 确保客户端实例的正确使用
python-binance的AsyncClient在多任务并发场景下,若共用单实例可能出现阻塞。可以为每个任务独立创建客户端,或全局复用但确保初始化逻辑正确:
import asyncio from binance import AsyncClient async def get_data(symbol, interval): # 每个任务单独初始化客户端 client = await AsyncClient.create(api_key='YOUR_KEY', api_secret='YOUR_SECRET') res = await client.get_klines( symbol=symbol, interval=interval, limit=10 ) await client.close_connection() return res async def main(): # 创建多个异步任务 tasks = [ asyncio.create_task(get_data('BTCUSDT', AsyncClient.KLINE_INTERVAL_1MINUTE)), asyncio.create_task(get_data('ETHUSDT', AsyncClient.KLINE_INTERVAL_1MINUTE)) ] # 等待所有任务完成并收集结果 results = await asyncio.gather(*tasks) print(results) if __name__ == "__main__": asyncio.run(main())
2. 规范事件循环管理
避免手动维护事件循环,优先使用asyncio.run()自动处理循环的创建与关闭。如果在Jupyter等特殊环境,需确保当前已有活跃事件循环,可通过asyncio.get_running_loop()获取并绑定任务。
3. 添加超时与异常处理
Binance API存在限流机制,并发过多会触发429错误导致任务挂起。为任务添加超时限制和异常捕获,避免无限等待:
async def get_data(symbol, interval): try: client = await AsyncClient.create(api_key='YOUR_KEY', api_secret='YOUR_SECRET') # 设置10秒超时,防止请求无响应 res = await asyncio.wait_for( client.get_klines(symbol=symbol, interval=interval, limit=10), timeout=10 ) await client.close_connection() return res except asyncio.TimeoutError: print(f"{symbol} 数据获取超时") return None except Exception as e: print(f"{symbol} 数据获取失败: {str(e)}") return None
4. 复用客户端实例的正确方式
若不想重复创建客户端,可全局初始化一个实例,在所有任务中复用,但必须确保客户端在事件循环内完成初始化:
import asyncio from binance import AsyncClient client = None async def init_client(): global client client = await AsyncClient.create(api_key='YOUR_KEY', api_secret='YOUR_SECRET') async def get_data(symbol, interval): global client res = await client.get_klines( symbol=symbol, interval=interval, limit=10 ) return res async def main(): await init_client() tasks = [ asyncio.create_task(get_data('BTCUSDT', AsyncClient.KLINE_INTERVAL_1MINUTE)), asyncio.create_task(get_data('ETHUSDT', AsyncClient.KLINE_INTERVAL_1MINUTE)) ] results = await asyncio.gather(*tasks) print(results) await client.close_connection() if __name__ == "__main__": asyncio.run(main())
内容的提问来源于stack exchange,提问作者Ramesses III
相关产品推荐
相关产品推荐

