Python中WebServer与Socket Server协同运行问题求助
你的Python多服务启动代码里的几个关键新手错误
咱们一步一步拆解你遇到的问题,先解决最直观的「打印不出来」问题,再搞定两个服务无法同时启动的核心矛盾:
1. 线程创建时踩了「直接调用函数」的经典大坑
你在WWW_Server模块里写的这行代码:
threading.Thread(target = srvThread(2000)).start()
这是Python线程创建的典型新手错误:你直接执行了srvThread(2000),而不是把函数对象传给target参数。
正常逻辑是,target需要接收一个不带括号的函数对象,线程启动后才会去执行这个函数。但你加了括号,就会在创建线程前立刻调用srvThread,而srvThread里的serve(app, ...)是个阻塞调用——Waitress的serve会一直占住当前线程不放,导致后面的print("hello")根本没机会执行,甚至连线程都没真正创建起来!
2. 模块导入触发的执行顺序陷阱
当你在主程序里写import WWW_Server时,Python会立刻执行模块里的所有顶级代码(也就是那个错误的线程创建逻辑)。这意味着主程序打印"one"之后,就直接卡在了WWW_Server模块的serve调用里,后续的print("two")、异步Socket服务启动代码全被堵死,根本跑不到。
3. 异步事件循环与阻塞服务的协同问题
即使解决了线程问题,主程序最后asyncio.get_event_loop().run_forever()也是阻塞的,但只要把Web服务放到独立线程里,异步Socket服务在主事件循环运行,两者就能和平共存——前提是线程创建逻辑正确。
修正后的代码示例
第一步:修复WWW_Server模块的线程创建
把模块代码改成这样,只传函数对象给target,用args传递参数:
from waitress import serve import threading # 假设你的Flask app已经在这里定义完成 app = ... def srvThread(SrvPort=5000): # 确保flaskThread()不是阻塞逻辑,只是初始化Flask相关内容 flaskThread() serve(app, host='0.0.0.0', port=SrvPort) # 正确创建线程:target传函数名(不带括号),args传参数元组 # daemon=True让线程随主程序退出而结束,避免主程序退出后线程残留 threading.Thread(target=srvThread, args=(2000,), daemon=True).start() print("hello") # 现在这个打印能正常输出了!
第二步:主程序的执行逻辑
现在导入模块后不会被阻塞,能正常启动异步Socket服务:
import asyncio import websockets import WWW_Server async def hello(websocket): # 你的websocket业务处理逻辑 pass start_server = websockets.serve(hello, "", 8765) print("one") print("two") # 现在这个打印也能正常输出了! asyncio.get_event_loop().run_until_complete(start_server) asyncio.get_event_loop().run_forever() print("three") # 这个依旧看不到,因为run_forever是阻塞调用,只有事件循环停止才会执行到这里
额外小提醒
- 如果你用的是Python 3.7+,推荐用
asyncio.run()替代get_event_loop(),代码更简洁安全。 - 确保
flaskThread()只是初始化逻辑,不是阻塞调用,否则即使放到线程里也会出问题。 - 生产环境中如果需要更稳定的多服务管理,可以考虑用多进程(
multiprocessing)代替多线程,或者用专门的服务管理工具,但新手阶段先把线程的基础逻辑搞对就足够了。
内容的提问来源于stack exchange,提问作者geoffr98
相关产品推荐
相关产品推荐

