Python函数外无法获取closePn值问题求助
解决Binance WebSocket回调外无法获取已收盘K线收盘价的问题
核心问题本质
你的问题根源是异步回调与同步代码的执行顺序冲突,再加上变量作用域/赋值时机的问题:
on_message是WebSocket客户端的异步回调函数,只有当服务器推送数据时才会触发执行- 外部代码如果在回调触发前就读取目标变量,自然拿不到有效数值;就算回调执行过,也可能因为变量作用域(比如局部变量未正确声明为全局或类属性)导致外部无法访问
可行解决方案
方案1:全局变量+同步锁(快速实现)
用全局变量存储收盘价,同时加锁避免多线程冲突(WebSocket回调通常在单独线程执行):
import websocket import json from threading import Lock import time import threading # 全局变量+锁,保证线程安全 latest_closed_close = None data_lock = Lock() def on_message(ws, message): global latest_closed_close data = json.loads(message) # 只处理已收盘的1小时K线(Binance用x字段标记是否收盘) if data['e'] == 'kline' and data['k']['x']: with data_lock: latest_closed_close = float(data['k']['c']) def on_error(ws, error): print(f"错误: {error}") def on_close(ws): print("WebSocket连接关闭") def on_open(ws): # 订阅BTCUSDT的1小时K线推送 ws.send('{"method": "SUBSCRIBE","params": ["btcusdt@kline_1h"],"id": 1}') if __name__ == "__main__": websocket.enableTrace(False) ws = websocket.WebSocketApp("wss://stream.binance.com:9443/ws", on_open=on_open, on_message=on_message, on_error=on_error, on_close=on_close) # 启动WebSocket客户端(后台线程) threading.Thread(target=ws.run_forever, daemon=True).start() # 外部读取收盘价的示例(循环定期检查) while True: with data_lock: if latest_closed_close is not None: print(f"最新已收盘1小时K线收盘价: {latest_closed_close}") time.sleep(60)
方案2:类封装(更优雅易维护)
把WebSocket逻辑和数据存储封装到类中,用实例属性存储收盘价,避免全局变量污染:
import websocket import json from threading import Lock import time import threading class BinanceKlineFetcher: def __init__(self): self.latest_closed_close = None self.data_lock = Lock() self.ws_client = None def on_message(self, ws, message): data = json.loads(message) # 过滤出已收盘的K线数据 if data['e'] == 'kline' and data['k']['x']: with self.data_lock: self.latest_closed_close = float(data['k']['c']) def on_error(self, ws, error): print(f"连接错误: {error}") def on_close(self, ws): print("WebSocket连接已关闭") def on_open(self, ws): ws.send('{"method": "SUBSCRIBE","params": ["btcusdt@kline_1h"],"id": 1}') def start(self): self.ws_client = websocket.WebSocketApp("wss://stream.binance.com:9443/ws", on_open=self.on_open, on_message=self.on_message, on_error=self.on_error, on_close=self.on_close) # 后台启动WebSocket服务 threading.Thread(target=self.ws_client.run_forever, daemon=True).start() def get_closed_close(self): with self.data_lock: return self.latest_closed_close if __name__ == "__main__": fetcher = BinanceKlineFetcher() fetcher.start() # 外部循环读取已收盘收盘价 while True: close_price = fetcher.get_closed_close() if close_price: print(f"已收盘1小时BTCUSDT收盘价: {close_price}") time.sleep(60)
关键注意事项
- Binance的K线推送中,
data['k']['x']是判断K线是否收盘的核心字段:True代表该K线已完全收盘,False代表正在运行中的K线 - 不需要用列表或numpy数组存储单个收盘价,直接存单个数值即可,避免不必要的复杂度
- 必须加同步锁:WebSocket回调在独立线程执行,外部读取时不加锁可能读取到未完成赋值的脏数据
内容的提问来源于stack exchange,提问作者Atila Hutter
相关产品推荐
相关产品推荐

