IBKR IbApi接收fundamentalData后连接无法断开问题求助
解决IBKR IbApi接收fundamentalData后连接无法断开的问题
你的代码核心问题在于self.run()是阻塞式事件循环调用,会持续占用当前线程导致后续代码无法执行;同时disconnect()调用后事件循环未正确终止,进而引发连接挂起。另外,time.sleep(2)是不可靠的等待方式,无法保证数据完整接收。
修正后的代码
import xmltodict from ibapi.client import * from ibapi.wrapper import * import threading from threading import Event class IBapi(EWrapper, EClient): def __init__(self): EWrapper.__init__(self) EClient.__init__(self, self) self.fundamental_data = {} self.data_received_event = Event() # 同步数据接收状态的事件标记 def fundamentalData(self, reqId: int, data: str): self.fundamental_data[reqId] = data print("已收到基本面数据") def fundamentalDataEnd(self, reqId: int): print("数据接收完成,开始断开连接") self.data_received_event.set() # 标记数据接收完成 self.disconnect() def error(self, reqId: int, errorCode: int, errorString: str): # 捕获API错误,避免程序意外挂起 print(f"错误信息: 请求ID={reqId}, 错误码={errorCode}, 描述={errorString}") self.data_received_event.set() self.disconnect() app = IBapi() app.connect("127.0.0.1", 7496, 0) # 单独线程运行事件循环,避免阻塞主线程 client_thread = threading.Thread(target=app.run) client_thread.start() # 构造合约并请求基本面数据 contract = Contract() contract.symbol = "AAPL" contract.secType = "STK" contract.exchange = "SMART" contract.currency = "USD" app.reqFundamentalData(1, contract, "CalendarReport", []) # 等待数据接收完成或触发错误 app.data_received_event.wait() # 等待事件循环线程完全退出 client_thread.join() # 处理并保存数据 if 1 in app.fundamental_data: data_dict = xmltodict.parse(app.fundamental_data[1]) with open("fundamental_data.xml", "w") as f: xmltodict.unparse(data_dict, output=f) print("基本面数据已写入文件 fundamental_data.xml") else: print("未成功获取基本面数据")
关键修改说明
- 用线程分离事件循环:将
app.run()放到独立线程执行,避免阻塞主线程后续逻辑。 - 用
Event替代time.sleep():通过事件标记精准等待数据接收完成,避免无效等待或提前执行后续代码。 - 完善异常处理:在
error回调中同样标记事件并断开连接,确保API出错时程序能正常终止。 - 线程同步等待:主线程等待事件触发后,再等待事件循环线程退出,保证连接完全断开后再处理数据。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

