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

如何在独立线程中运行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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 19:14:54