如何重启FastAPI创建的Web服务器?(PySide6界面+PyInstaller打包场景)
实现FastAPI服务的重启功能
要实现重启,核心是先终止当前运行的uvicorn进程,再重新启动,以下是具体实现步骤:
1. 改造启动逻辑,保存进程实例
原来的启动方式如果未保存进程句柄,需改用subprocess.Popen启动服务,这样能拿到进程对象,方便后续终止操作。示例代码:
import subprocess from PySide6.QtWidgets import QPushButton, QWidget from PySide6.QtCore import QThread class ServerThread(QThread): def __init__(self): super().__init__() self.server_process = None def run(self): # 启动uvicorn服务,用Popen保存进程实例 self.server_process = subprocess.Popen( ["uvicorn", "easydemo:app", "--host", "0.0.0.0", "--port", "8000"], shell=True # 打包成exe后需开启shell,确保命令能被正确执行 ) # 等待进程结束 self.server_process.wait() def stop_server(self): if self.server_process and self.server_process.poll() is None: # 终止进程 self.server_process.terminate() # 等待进程完全退出 self.server_process.wait() self.server_process = None class MainWindow(QWidget): def __init__(self): super().__init__() self.server_thread = ServerThread() # 初始化按钮 self.start_btn = QPushButton("启动", self) self.start_btn.clicked.connect(self.start_server) self.stop_btn = QPushButton("停止", self) self.stop_btn.clicked.connect(self.stop_server) self.stop_btn.setEnabled(False) self.restart_btn = QPushButton("重启", self) self.restart_btn.clicked.connect(self.restart_server) self.restart_btn.setEnabled(False) def start_server(self): if not self.server_thread.isRunning(): self.server_thread.start() self.start_btn.setEnabled(False) self.stop_btn.setEnabled(True) self.restart_btn.setEnabled(True) def stop_server(self): if self.server_thread.isRunning(): self.server_thread.stop_server() self.server_thread.wait() self.start_btn.setEnabled(True) self.stop_btn.setEnabled(False) self.restart_btn.setEnabled(False) def restart_server(self): # 先执行停止操作 self.stop_server() # 再重新启动服务 self.start_server()
2. 打包成exe后的细节处理
- 用PyInstaller打包时,需在spec文件中添加uvicorn相关隐式依赖:
hiddenimports=["uvicorn", "uvicorn.logging", "uvicorn.loops", "uvicorn.protocols", "uvicorn.protocols.http", "uvicorn.protocols.websockets"] - 若需要保留CMD窗口,无需额外配置;若想隐藏窗口,可在
subprocess.Popen中添加creationflags=subprocess.CREATE_NO_WINDOW(仅Windows有效)。 - 确保
easydemo.py与主脚本在同一目录,打包时将其包含进exe资源中。
3. 异常处理优化
为避免进程卡死或已退出时报错,可在停止逻辑中添加超时与异常捕获:
def stop_server(self): if self.server_process and self.server_process.poll() is None: try: self.server_process.terminate() # 设置5秒超时,超时则强制杀死进程 self.server_process.wait(timeout=5) except subprocess.TimeoutExpired: self.server_process.kill() finally: self.server_process = None
内容的提问来源于stack exchange,提问作者iknow34languages
相关产品推荐
相关产品推荐

