You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python websockets的on_message函数无法传参时,除global外有什么替代方案

不用global关键字的实现方案

以下方案均可以保留跨消息的状态持久化,不需要每次接收消息时重置变量:


1. 类封装状态(最推荐)

把所有交易相关的参数、状态变量、回调逻辑都封装到同一个类中,on_message作为类的实例方法,通过self访问所有状态变量,完全不需要全局变量,可维护性最高,也方便后续扩展功能。
示例代码:

import json
import websocket

class TradingBot:
    def __init__(self):
        # 初始化所有参数和状态
        self.Symbol = "BTCUSDT"
        self.interval = "1m"
        self.EMA_period = 28
        self.MACD_fast_period = 12
        self.MACD_slow_period = 26
        self.MACD_signal_period = 9
        self.historic_highs = []
        self.historic_lows = []
        self.historic_closes = []
        self.MACD_CrossBool = [None, None]
        self.in_position = False
        # 其他需要的参数也可以放在这里

    def on_message(self, ws, message):
        # ------------------------- 解析JSON消息数据 ------------------------- #
        json_message = json.loads(message)
        candle = json_message['k'] # 访问K线数据

        # ......[其他代码省略]......

        if MACD_CrossOver == True and trend == 1:
            if not self.in_position:
                print("买入订单")
                self.in_position = True

        if MACD_CrossUnder == True and trend == -1:
            if not self.in_position:
                print("卖出订单")
                self.in_position = True

        # ......[其他代码省略]......

        if self.in_position:
            if buy_order['status'] and close <= long_stop_price:
                sell_order = margin_order(buy_order['symbol'], SIDE_SELL, buy_order['quantity'], close, ORDER_TYPE_LIMIT)
                print("多头止损触发")

            if sell_order['status'] and close >= short_stop_price:
                buy_order = margin_order(sell_order['symbol'], SIDE_BUY, sell_order['quantity'], close, ORDER_TYPE_LIMIT)
                print("空头止损触发")

# 实例化后绑定回调
if __name__ == "__main__":
    bot = TradingBot()
    ws = websocket.WebSocketApp(
        url="你的websocket连接地址",
        on_message=bot.on_message
        # 其他回调比如on_error、on_close也可以绑定bot的对应方法
    )
    ws.run_forever()

2. 可变容器包装状态(改动最小)

Python中只有对变量重新赋值时才需要声明global,如果是修改可变对象(列表、字典)的内部元素,不需要声明全局。你可以把布尔类型的in_position包装到列表或者字典这类可变容器中,仅改一行定义就能解决问题。
示例代码:

# 原来的定义:in_position = False
# 改成用长度为1的列表包装
in_position = [False]

def on_message(ws, message):
    # 不需要加global声明
    json_message = json.loads(message)
    candle = json_message['k']

    # ......[其他代码省略]......
    if MACD_CrossOver == True and trend == 1:
        # 读写都用下标访问第一个元素
        if not in_position[0]:
            print("买入订单")
            in_position[0] = True
    # 其他用到in_position的地方全部改成in_position[0]即可

3. 闭包封装状态

用外层函数包裹所有状态变量,返回on_message回调函数,内部通过nonlocal关键字修改外层作用域的变量,不会污染全局命名空间。
示例代码:

def create_trading_callback():
    Symbol = "BTCUSDT"
    interval = "1m"
    EMA_period = 28
    MACD_fast_period = 12
    MACD_slow_period = 26
    MACD_signal_period = 9
    historic_highs = []
    historic_lows = []
    historic_closes = []
    MACD_CrossBool = [None, None]
    in_position = False

    def on_message(ws, message):
        # 声明需要修改外层作用域的变量
        nonlocal in_position
        json_message = json.loads(message)
        candle = json_message['k']

        # ......[其他代码省略]......
        if MACD_CrossOver == True and trend == 1:
            if not in_position:
                print("买入订单")
                in_position = True
        # 其他逻辑和原来完全一致
    return on_message

# 绑定回调时传入生成的on_message函数
if __name__ == "__main__":
    on_message_cb = create_trading_callback()
    ws = websocket.WebSocketApp(
        url="你的websocket连接地址",
        on_message=on_message_cb
    )
    ws.run_forever()

4. 用functools.partial绑定状态参数

你可以提前把状态变量包装到字典里,用functools.partial把状态字典绑定为on_message的额外参数,不需要改动回调的核心逻辑。
示例代码:

from functools import partial

# 把所有状态放到字典中
state = {
    "Symbol": "BTCUSDT",
    "interval": "1m",
    "EMA_period": 28,
    "MACD_fast_period": 12,
    "MACD_slow_period": 26,
    "MACD_signal_period": 9,
    "historic_highs": [],
    "historic_lows": [],
    "historic_closes": [],
    "MACD_CrossBool": [None, None],
    "in_position": False
}

# 给on_message加一个state参数
def on_message(state, ws, message):
    json_message = json.loads(message)
    candle = json_message['k']

    # ......[其他代码省略]......
    if MACD_CrossOver == True and trend == 1:
        if not state["in_position"]:
            print("买入订单")
            state["in_position"] = True
    # 其他用到状态的地方都从state字典里取

# 绑定回调时用partial把state传进去
if __name__ == "__main__":
    bound_on_message = partial(on_message, state)
    ws = websocket.WebSocketApp(
        url="你的websocket连接地址",
        on_message=bound_on_message
    )
    ws.run_forever()

内容的提问来源于stack exchange,提问作者Mo0rBy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 13:36:03