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

Python调用websocket-client的run_forever时脚本挂起如何解决

问题根因

故障核心原因是websocket-client的run_forever()是阻塞调用:这个方法会启动独占的无限事件循环,只要连接不主动断开就永远不会返回,直接占满运行它的主线程。你写在调用语句之后的所有游戏逻辑、事件监听、屏幕阅读器交互代码完全得不到执行机会,才会出现服务端显示连接已建立,但游戏整体卡死、按Ctrl+C打断阻塞后才恢复的现象。

你现有代码的具体问题:

  • sockopen()调用run_forever()后没有任何返回值,主程序里ws=network.sockopen()拿到的永远是None,后续调用发送接口传空值会直接触发错误
  • 游戏核心的lucia.process_events()事件处理写在sockopen()调用之后,阻塞期间输入响应、音频输出、屏幕阅读器的调度完全停摆,自然会出现卡顿假死
  • sockopen()内创建的WebSocket实例是局部变量,和你声明的全局socket没有绑定,外部代码根本访问不到已建立的连接
  • 代码里写的time.sleep(10)会无意义卡住主线程10秒,进一步加剧无响应问题

修复方案

第一步:将websocket事件循环放到独立后台线程运行

不要让run_forever()占用游戏主线程,单独开守护线程跑websocket的事件循环,不阻塞主线程的游戏逻辑调度。
修改network模块的sockopen函数:

import websocket
import threading
import time

# 全局连接实例初始化
socket = None

def sockopen():
    global socket
    socket = websocket.WebSocketApp(
        "ws://"+host+port,
        on_message=on_message,
        on_error=on_error,
        on_close=on_close
    )
    # 开守护线程运行websocket无限循环,随主程序退出自动销毁
    ws_thread = threading.Thread(target=socket.run_forever, daemon=True)
    ws_thread.start()
    # 短暂等待确保连接建立完成再返回
    time.sleep(0.5)
    return socket

第二步:调整主程序逻辑,保证事件循环持续调度

把websocket初始化放到游戏循环外,不要重复建连,确保每帧优先处理系统事件,避免屏幕阅读器、输入、音频卡顿。
修改主程序的onlinegame部分:

def onlinegame(wearein):
    # 初始化websocket连接,后台运行不阻塞主线程
    ws = network.sockopen()
    while True:
        # 每帧最先处理系统事件,保证交互响应不中断
        lucia.process_events()
        if lucia.key_pressed(pygame.K_ESCAPE):
            ws.close()
            logoff()

        # 原有菜单、游戏逻辑正常执行,不会被websocket阻塞
        if(wearein=="mainmenu"):
            client=lucia.show_window("The Pale Blue Dot, menu principal")
            mainmenu=main.mainmenu()

            if(mainmenu=="register"):
                print("register\n")
                network.query_send(ws,"account&&initplayer&&ID",False)
                wearein="register"
            if(mainmenu=="login"):
                print("connection")
                wearein="login"
            if(mainmenu=="quite"):
                ws.close()
                logoff()

        if(wearein=="register"):
            client=lucia.show_window("the pale blue dot, création d'un compte")
        
        # 加短延时避免CPU空转占满资源
        time.sleep(0.01)

额外注意事项
  • 不要在on_message这类websocket回调里写耗时操作,回调运行在websocket独立线程中,耗时逻辑会卡消息接收
  • 如果websocket收到消息需要触发游戏内音频播放、界面更新,建议用线程安全的队列传递数据,不要直接在websocket线程里调用lucia的接口,避免多线程冲突导致崩溃
  • 后续如果需要主动断开websocket,直接调用ws.close()即可,对应的on_close回调会正常触发

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 01:12:26