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
相关产品推荐
相关产品推荐

