如何在独立线程中运行WebSocket服务器?Python桌面应用技术求助
解决方案:在独立线程中运行异步WebSocket服务器
你的核心问题在于异步函数无法直接作为线程目标,原代码中threading.Thread(target=await self.websocket.start)的写法完全错误——target需要传入可调用对象,而不是await执行后的结果。此外,异步函数必须在asyncio事件循环中运行,子线程默认没有事件循环,需要手动初始化。
以下是修正后的完整实现:
修正后的主代码
import asyncio import webview import threading from services.HttpServer import HttpServerService from services.WebSocket import WebSocketService def on_loaded(window_ready): webview.windows[0].events.loaded -= on_loaded print('Val', window_ready) if window_ready: webview.windows[0].set_window_size(width=1200, height=800) # WebSocket线程的入口函数,负责创建事件循环并运行服务 def run_websocket_service(websocket_service): loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) loop.run_until_complete(websocket_service.start()) loop.close() class App: def __init__(self): self.http_server_thread = None self.websocket_thread = None self.client_ui_thread = None self.websocket = None self.client_ui = None self.webview = webview async def start(self): # 启动HTTP服务线程(原代码无问题,保留) self.http_server_thread = threading.Thread(target=HttpServerService("127.0.0.1", 8001).start) self.http_server_thread.daemon = True self.http_server_thread.start() # 初始化WebSocket服务并启动独立线程 self.websocket = WebSocketService("127.0.0.1", 8008) self.websocket_thread = threading.Thread(target=run_websocket_service, args=(self.websocket,)) self.websocket_thread.daemon = True self.websocket_thread.start() # 启动GUI线程(原代码无问题,保留) self.client_ui = webview.create_window("CrowdQuant", url="http://127.0.0.1:8001", width=1024, height=770, resizable=False, frameless=True) self.client_ui.events.loaded += lambda: self.websocket.on_message(variable_name="window_ready", handle_message_fn=on_loaded) self.client_ui_thread = threading.Thread(target=webview.start) self.client_ui_thread.daemon = True self.client_ui_thread.start() if __name__ == "__main__": asyncio.run(App().start())
补充WebSocketService的缺失方法
原代码中handle_message、on_message等核心方法未实现,导致运行报错,这里补充基础实现:
import json import asyncio import websockets class WebSocketService: def __init__(self, address="127.0.0.1", port=8008): self.socket = None self.url = (address, port) self.variable_name = None self.handle_message_fn = None self.server = None self.clients = set() async def start(self): await self.start_server() # 若不需要内置客户端连接,可注释或移除start_client调用 # await self.start_client() async def start_server(self): while True: try: self.server = await websockets.serve(self.handle_client_connection, self.url[0], self.url[1]) print(f"WebSocket server started at ws://{self.url[0]}:{self.url[1]}") await self.server.wait_closed() except OSError: print(f"Address {self.url[0]}:{self.url[1]} already in use. Retrying...") await asyncio.sleep(5) async def handle_client_connection(self, websocket): self.clients.add(websocket) try: async for message in websocket: await self.handle_message(message) finally: self.clients.remove(websocket) # 消息处理核心逻辑 async def handle_message(self, message): print(f"Received message: {message}") # 调用注册的GUI回调函数 if self.handle_message_fn: try: data = json.loads(message) if data.get("variable_name") == self.variable_name: self.handle_message_fn(data.get("value")) except json.JSONDecodeError: print("Invalid JSON message") # 注册消息回调(原代码中被调用但未实现) def on_message(self, variable_name, handle_message_fn): self.variable_name = variable_name self.handle_message_fn = handle_message_fn async def start_client(self): # 若需要WebSocket客户端连接,实现此处逻辑 pass async def stop(self): await self.stop_client() await self.stop_server() async def stop_server(self): if self.server: self.server.close() await self.server.wait_closed() async def stop_client(self): if self.socket and self.socket.open: await self.socket.close() @staticmethod def on_error(error): print('WebSocket error:', error)
关键说明
- 新增
run_websocket_service函数:作为线程入口,手动创建asyncio事件循环并运行WebSocket服务,解决子线程无事件循环的问题 - 修正线程启动逻辑:将
target改为指向run_websocket_service,并传入WebSocketService实例作为参数,避免直接调用异步函数 - 补充WebSocketService中缺失的核心方法:确保消息处理和事件注册逻辑正常运行
内容的提问来源于stack exchange,提问作者Tebyy
相关产品推荐
相关产品推荐

