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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 22:30:33