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

使用cx_Freeze打包后Python subprocess执行超时卡住问题排查

可能的原因及解决办法

以下是导致cx_Freeze打包后应用卡住的几个核心原因,以及对应的修复方案:

1. shell=True导致PID指向错误进程

当设置shell=True时,subprocess.Popen实际启动的是系统cmd.exe进程,而非目标的STM32_Programmer_CLI.exe。此时process.pid是cmd.exe的PID,调用os.kill仅终止shell进程,真正的CLI工具可能仍在后台运行,导致主进程的while循环一直检测到子进程未结束,永久卡住。

解决办法:
去掉shell=True参数,直接启动目标程序,确保process.pid对应正确进程:

process = subprocess.Popen(
    [
        'STM32_Programmer_CLI.exe',
        '-c',
        'port=SWD',
        'freq=4000',
    ],
    text=True,
    cwd=self.cubeProgPath,
    stdout=subprocess.PIPE
)

注意:若STM32_Programmer_CLI.exe不在系统PATH中,需传入绝对路径,或确保cwd指向工具所在的正确目录。

2. 未读取标准输出导致管道阻塞

代码中设置了stdout=subprocess.PIPE但未读取输出,当子进程输出填满管道缓冲区时,子进程会被挂起,无法退出,进而导致主进程的while循环一直等待,形成死锁。脚本运行时可能因终端缓冲机制或输出量小未触发,但打包成独立exe后更容易出现。

解决办法:

  • 若不需要输出,直接丢弃:
    stdout=subprocess.DEVNULL
    
  • 若需要输出,在循环中定期读取缓冲区:
    while True:
        # 读取一行输出,避免缓冲区阻塞
        line = process.stdout.readline()
        if line:
            # 按需处理输出内容
            pass
        
        if process.poll() is not None:
            res = True
            break
        elif (time.time() - stamp) > myTimeout:
            process.terminate()
            break
    

3. CTRL_C_EVENT信号无法正确生效

Windows系统中,signal.CTRL_C_EVENT需要发送到控制台进程组,cx_Freeze打包后的exe可能无法将信号正确传递给子进程(尤其是shell=True时,信号仅发给shell进程,不会转发给子进程)。超时后子进程无法终止,主进程持续卡在循环中。

解决办法:
使用process.terminate()或process.kill()替代os.kill,这两个方法更可靠,直接终止子进程:

# 超时终止时替换为
process.terminate()  # 优雅终止,等价于TerminateProcess
# 或强制终止
# process.kill()

4. 工作路径cwd在打包后失效

打包后的exe运行时,self.cubeProgPath指向的路径可能与脚本运行时不同(比如exe所在目录变化),导致子进程无法找到STM32_Programmer_CLI.exe,但shell=True会让shell进程仅报错而不退出,主进程循环一直检测到进程未结束。

解决办法:
动态获取打包后的exe所在目录,拼接工具路径:

import sys
import os

# 获取当前exe所在目录
exe_dir = os.path.dirname(sys.executable)
# 假设工具与exe在同一目录
tool_path = os.path.join(exe_dir, 'STM32_Programmer_CLI.exe')

process = subprocess.Popen(
    [tool_path, '-c', 'port=SWD', 'freq=4000'],
    text=True,
    stdout=subprocess.PIPE
)

额外代码问题

你的异常捕获语法错误,应写成except Exception as e:而非except e:,这会导致脚本遇到异常时无法正确处理,打包后可能引发未预期错误。


内容的提问来源于stack exchange,提问作者WITC

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 03:15:43