PyQt5打包后subprocess无法启动Socket服务器问题求助
问题:PyQt5界面打包后无法启动Socket服务器
我有一个运行正常的Socket服务器,用PyQt5做了带“启动服务器”“关闭服务器”按钮的极简界面,通过subprocess实现启停逻辑。在PyCharm中运行完全正常,但用auto-py-to-exe打包后,点击启动按钮会生成新进程PID,但服务器实际未启动。使用Python3.8.2(客户要求),以下是相关代码和已尝试的方案:
现有启停代码
启动服务器代码
def start_serv(self): self.process = subprocess.Popen('python server.py', shell=True) logging.info('#' * 80) logging.debug(f'Process PID: {self.process.pid}') logging.debug(f'Child process return code: {self.process.returncode}') self.mb('The server is running!') # 弹出提示对话框
关闭服务器代码
def stop_serv(self): try: proc = self.process proc.send_signal(signal.SIGTERM) while True: ex_code = proc.poll() if ex_code == None or ex_code == '1': proc.wait() continue else: break logging.debug(f'Child process exit code: {proc.poll()}') logging.debug('The server is stopped!') logging.info('#' * 80) self.mb('The server is stopped!') # 弹出提示对话框 except Exception as e: logging.warning(f'Error button: {e}') self.mb('The server is not running yet!') # 弹出提示对话框
已尝试的路径设置(均无效)
第一种:
self.path_server = Path(Path.cwd(), 'server.py') self.process = subprocess.Popen(f'python {self.path_server}', shell=True)
第二种:
cwd = os.path.dirname(os.path.abspath(__file__)) self.process = subprocess.Popen('python server.py', shell=True, cwd=cwd)
解决方案
1. 打包时确保包含server.py
在auto-py-to-exe的Additional Files选项中,添加server.py文件,确保打包后的程序能找到该文件。
2. 使用sys.executable替代python命令
打包后的环境中,直接调用python可能指向系统默认Python,而非打包时的解释器,导致依赖缺失。改用sys.executable调用当前程序使用的Python解释器:
import sys import os def start_serv(self): # 获取打包后server.py的正确路径 if hasattr(sys, '_MEIPASS'): # 打包后临时目录 server_path = os.path.join(sys._MEIPASS, 'server.py') else: # 开发环境路径 server_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'server.py') # 使用sys.executable调用,关闭shell=True避免额外进程 self.process = subprocess.Popen( [sys.executable, server_path], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) # 打印错误信息排查问题 try: stdout, stderr = self.process.communicate(timeout=1) if stderr: logging.error(f'Server start error: {stderr}') self.mb(f'Start failed: {stderr}') return except subprocess.TimeoutExpired: # 服务器启动可能需要时间,超时说明进程已启动 pass logging.info('#' * 80) logging.debug(f'Process PID: {self.process.pid}') self.mb('The server is running!')
3. 优化关闭服务器逻辑
SIGTERM在Windows系统下兼容性较差,改用terminate(),并简化等待逻辑:
def stop_serv(self): try: proc = self.process proc.terminate() # 等待进程结束,设置超时避免无限等待 proc.wait(timeout=5) ex_code = proc.returncode logging.debug(f'Child process exit code: {ex_code}') logging.debug('The server is stopped!') logging.info('#' * 80) self.mb('The server is stopped!') except subprocess.TimeoutExpired: # 超时则强制杀死进程 proc.kill() logging.warning('Server process killed after timeout') self.mb('Server stopped forcefully!') except Exception as e: logging.warning(f'Error button: {e}') self.mb('The server is not running yet!')
4. 验证打包配置
优先选择auto-py-to-exe的One Directory模式(而非One File),更容易排查文件路径问题;若必须用One File,确保server.py被正确打包到临时目录。
内容的提问来源于stack exchange,提问作者Pavel_G
相关产品推荐
相关产品推荐

