维护说明(2026 年 9 月): 标题中的“已解决”只描述 2019 年一台电脑上的结果,并非通用修复方案。原文把可执行文件硬链接到
pyqt5_tools的内部路径中;这种做法可能掩盖环境错配,并在更新后再次失效。下面的维护版先做只读诊断,使用当前环境自己的工具,并在文末完整保留原文;仅为仓库格式规范化不可见的行尾空格。
错误消息给出了一个可执行文件,却没有指出究竟是哪一层失败。Qt Designer 的常规 uic 工作流从 .ui 文件生成 C++,PyQt5 的 pyuic5 生成 Python,而第三方 pyqt5-tools 又增加了自己的 Designer 启动器和兼容桥接。修改文件之前,应把它们当作三个不同的工具来诊断。
Table of Contents
2019 年的变通方法证明了什么,又没有证明什么
当时的电脑上存在这两个文件:
C:Miniconda3Libsite-packagespyqt5_toolsuic.exe
C:Miniconda3Scriptspyuic5.exe
而 Designer 查找的是:
C:Miniconda3Libsite-packagespyqt5_toolsbinuic.exe
硬链接让这次查找成功。它只证明 Designer 能在那次安装中执行被链接的文件;它不能证明另一套 pyqt5-tools、PyQt5、Qt、Python、Conda 或 Windows 版本也应该使用同样的目录结构。
存档还声称 Windows 无法创建硬链接。这并不正确:Microsoft 为 NTFS 记录了 fsutil hardlink create。不过,硬链接仍不是这里适合优先采用的修复,因为它复制了对包内部路径的假设,不受包元数据管理,并且任一包替换后都可能过时。下面的诊断和推荐工作流不需要第三方外壳扩展。

先确定真正需要的结果
| 目标 | 对应的工具边界 | 推荐路线 |
|---|---|---|
从 form.ui 生成 Python | PyQt5 pyuic5 或 PyQt5.uic | 使用当前项目的 Python 环境转换;Designer 的 View Code 菜单并非必需。 |
| 预览或生成 Qt/C++ 代码 | Qt Designer 和 Qt uic | 使用配套的 Qt 工具集,不要用任意 PyQt 启动器替换 Qt 编译器。 |
启动 pyqt5-tools 随附的 Designer | 第三方 pyqt5-tools 包装器 | 从拥有该包的同一环境运行包装器,并核对该版本的帮助。 |
在运行时加载 .ui 文件 | PyQt5 uic.loadUi() 或生成的模块 | 在整个项目中选择一种工作流,并用部署时的 PyQt5 版本测试。 |
Riverbank 把 pyuic5 定义为 PyQt5 uic 模块的命令行接口。Qt 则说明 Designer 的 .ui 文件是 XML,而其常规 uic 输出是 C++ 代码。理解这个区别,就能看出 Designer 的 View Code 失败并不自动意味着 PyQt5 导入或 Python 代码生成也坏了。
1. 在不改动环境的前提下记录现场
打开项目实际使用的 Conda 提示符或 PowerShell 会话。把 PROJECT_ENV 换成目标环境名,不要默认 base 就是正确环境。
conda info --envs
conda activate PROJECT_ENV
Get-Command python -All
Get-Command pyuic5 -All -ErrorAction SilentlyContinue
Get-Command pyqt5-tools -All -ErrorAction SilentlyContinue
python -c "import sys; print(sys.executable); print(sys.version)"
python -m pip --version
python -m pip show --files PyQt5 pyqt5-tools
python -m pip check
conda list | Select-String -Pattern '^(pyqt|qt|python|pip)s'
保存完整输出。sys.executable 标识实际运行的解释器,Get-Command -All 会暴露其他环境中被遮蔽的命令,pip show --files 列出包拥有的文件,pip check 报告缺失或不兼容的 Python 依赖。这些命令都不会重装或删除任何内容。
2. 给准确的失败类型分类
| 症状 | 可能类别 | 含义 |
|---|---|---|
Designer 报 Unable to launch ...pyqt5_toolsbinuic.exe | Designer 辅助程序路径/布局 | Designer 在某个包特定路径中期待一个不存在的辅助程序;单凭这一点无法判断 pyuic5 是否正常。 |
pyuic5.exe 报 Fatal error in launcher 或提到旧 Python 路径 | 过期的入口包装器/解释器 | Python 安装工具会在环境的 Scripts 目录创建 Windows 命令包装器。复制或移动环境可能让包装器仍指向旧解释器。在 Unix 中常把这类问题称为 shebang 问题;不要十六进制编辑 Windows .exe。 |
系统提示无法识别 pyuic5 | 激活/PATH | 目标环境未激活、它的 Scripts 目录不在 PATH 中,或入口点没有安装。 |
ModuleNotFoundError: PyQt5 | 解释器错误或发行包缺失 | 对照 sys.executable、Get-Command python 和 python -m pip show PyQt5。 |
DLL load failed、插件加载错误或依赖不兼容 | 二进制/版本/工具集错配 | 改包之前核对 Python 架构以及 PyQt5、Qt、插件和工具的精确版本。 |
| 转换成功运行,但生成的代码失败 | .ui/资源/API 兼容性 | 用最小 .ui 文件和相同 PyQt5 版本复现;这不是启动器路径修复。 |
措辞很重要。保存完整控制台错误以及产生错误的准确菜单或命令;只截取最后一行会丢失解释器与路径证据。
3. 检查环境拥有的路径
激活目标环境后,让 PowerShell 推导环境根目录,不要硬编码 C:Miniconda3:
$pythonPath = (Get-Command python).Source
$environmentRoot = Split-Path $pythonPath
$scriptsPath = Join-Path $environmentRoot 'Scripts'
$historicalHelper = Join-Path $environmentRoot 'Libsite-packagespyqt5_toolsbinuic.exe'
$pythonPath
$environmentRoot
Test-Path -LiteralPath $scriptsPath -PathType Container
Test-Path -LiteralPath (Join-Path $scriptsPath 'pyuic5.exe') -PathType Leaf
Test-Path -LiteralPath (Join-Path $scriptsPath 'pyqt5-tools.exe') -PathType Leaf
Test-Path -LiteralPath $historicalHelper -PathType Leaf
Get-ChildItem -LiteralPath $environmentRoot -Filter uic.exe -Recurse -ErrorAction SilentlyContinue
把结果与 python -m pip show --files 对照。某个文件存在于环境中的某处,并不能证明 Designer 应该使用它。同样,手工复制 .exe 不会登记文件归属,也不能让它的解释器与 Qt 依赖自动匹配。
4. 不依赖 Designer 的 View Code 生成 Python
如果真正目标是 Python 输出,先运行环境中由 PyQt5 记录的命令,并写入新文件,以免覆盖已有生成模块:
pyuic5 .form.ui -o .ui_form_generated.py
python -m py_compile .ui_form_generated.py
替换任何已纳入版本控制的生成文件之前先检查差异。Riverbank 提醒,生成代码取决于生成时的 PyQt5 版本,因此应该使用应用部署的版本重新生成并测试。
如果 PyQt5 可以导入,只有 pyuic5.exe 启动器过期,下面的小脚本会直接调用官方 PyQt5.uic.compileUi() API。它先在内存中验证生成源码,再以原子替换方式只更新新的输出文件:
from io import StringIO
import os
from pathlib import Path
from tempfile import NamedTemporaryFile
from PyQt5 import uic
source = Path("form.ui")
target = Path("ui_form_generated.py")
buffer = StringIO()
uic.compileUi(str(source), buffer, from_imports=True)
generated = buffer.getvalue()
compile(generated, str(target), "exec")
temporary_path = None
try:
with NamedTemporaryFile(
"w",
encoding="utf-8",
newline="n",
dir=target.parent,
prefix=target.name + ".",
suffix=".tmp",
delete=False,
) as temporary:
temporary.write(generated)
temporary_path = Path(temporary.name)
os.replace(temporary_path, target)
temporary_path = None
finally:
if temporary_path is not None:
try:
temporary_path.unlink()
except FileNotFoundError:
pass
使用前面由 sys.executable 确认的解释器运行脚本,再执行 python -m py_compile .ui_form_generated.py。这种方法绕过损坏的控制台启动器,但不会修复 Designer 的内部辅助程序路径。
5. 只修复失败层,不要重装所有包
A. 过期启动器或混合环境
先保存回滚记录:
conda list --explicit > .conda-explicit-before.txt
python -m pip freeze > .pip-before.txt
优先使用项目已记录的依赖或锁文件创建一个并列环境。在修改 IDE 解释器或删除旧环境之前,先验证新环境。Conda 当前指南建议隔离环境;如果使用 pip 后还需要更改,建议重建环境。
不要移动虚拟/Conda 环境目录、只复制 pyuic5.exe、编辑启动器二进制文件,或把所有 Python Scripts 目录都加入全局 PATH。这些方法会让命令解析更难复现。
B. 缺少 pyqt5-tools Designer 桥接
pyqt5-tools 是第三方辅助项目,并不是 Riverbank 的 PyQt5 wheel 一部分。它当前的 PyPI 页面把项目标为 Beta,显示最近一次发布在 2023 年 3 月,声明需要 Python 3.7 或更高版本,而 Python 分类器只列到 3.9。这些元数据只能作为兼容性线索,不能证明某个特定 Python/Qt 组合一定可用。
项目目前为 Designer 代码查看记录了一个与版本有关的 installuic 子命令。同一页面却意外提到复制 pyuic6.exe,并表示 Designer 的一个菜单路径仍然损坏。鉴于这种不一致,只应在可丢弃或容易重建的并列环境中测试:
& "$env:CONDA_PREFIXScriptspyqt5-tools.exe" --help
& "$env:CONDA_PREFIXScriptspyqt5-tools.exe" installuic --help
只有在已安装版本的帮助与包文档都符合当前环境时,才运行子命令本身:
& "$env:CONDA_PREFIXScriptspyqt5-tools.exe" installuic
随后重新运行路径清单与转换测试。如果目的只是从 .ui 生成 Python,则不要使用这个桥接;pyuic5 或 PyQt5.uic 已经提供受支持的 PyQt5 边界。
C. 版本或二进制错配
不要从未锁定版本的“全部重装”开始。保留失败环境,阅读依赖解析器的错误,并在新环境中测试兼容的 Python/PyQt5/tools 组合。包是否可用取决于 Python 版本、架构和平台。成功安装只是第一关:pip check、导入、转换、编译和 Designer 启动都必须通过。
D. 真正目标是 Qt/C++ View Code
使用与 Designer 来自同一个 Qt 发行版的 uic。Qt 的官方工作流从 XML .ui 文件生成 C++ 头文件。除非所选第三方桥接针对其精确版本明确记录了这种行为,否则 PyQt 专用辅助程序不是正确替代品。
6. 验证、接受与回滚
使用真实 .ui 文件的一份小型副本,并记录以下矩阵:
| 检查 | 通过条件 |
|---|---|
| 解释器 | sys.executable 指向目标环境内部。 |
| 依赖 | python -m pip check 没有报告损坏的依赖。 |
| PyQt5 导入 | python -c "from PyQt5 import uic; print(uic.__file__)" 指向该环境内部。 |
| 转换 | pyuic5 或 API 脚本创建新的 Python 文件,并且不修改 .ui 源文件。 |
| 语法 | python -m py_compile .ui_form_generated.py 成功。 |
| 应用 | 生成的窗体能在项目自己的冒烟测试中导入并打开。 |
| Designer(如需要) | 同一环境的包装器能启动 Designer,且 View Code 生成预期语言。 |
只有从全新终端连续两次通过所有必需项目,才接受修复。如果并列环境失败,停用它,并把 IDE 指回未改动的旧解释器;已保存的清单仍可作为证据。在项目测试套件和一次正常开发会话都通过之前,保留旧环境。
应避免的脆弱修复
- 把
uic.exe硬链接或复制到未记录的site-packages子目录。 - 从一个环境把
pyuic5.exe复制到另一个环境。 - 编辑生成的 Windows 启动器,或假设每个启动器故障都是文本 shebang 问题。
- 安装到 Conda
base,在 Conda 内使用pip --user,或在全局PATH中混合多个环境。 - 在保留版本与原始错误之前,一次性重装 PyQt5、Qt、Designer 和插件。
- 把 Designer View Code 当成从
.ui生成 Python 的唯一方法。
一手文档
- Riverbank:在 PyQt5 中使用 Qt Designer
- Riverbank:`PyQt5.uic` 模块与 `compileUi()`
- Qt 5.15:在 C++ 应用中使用 Designer UI 文件
- Python Packaging Authority:入口点命令包装器
- pip:`pip show --files`
- pip:`pip check`
- Conda:管理与重建环境
- Microsoft:`Get-Command`
- Microsoft:`Test-Path`
- Microsoft:`fsutil hardlink`
- PyPI 上的 `pyqt5-tools` 项目元数据与用法
2019 年原文(完整存档)
存档来源: 以下正文复制自
out/posts/2019-05-01-unable-to-launch-cminiconda3libsite-packagespyqt5_toolsbinuic-exe-1925/index.md,文章 ID 为1925,日期为 2019-05-01。完整可见文字、拼写、大小写、相对图片路径以及错误的硬链接说法均予以保留;仅为仓库格式规范化不可见的行尾空格。请勿把它当作当前操作指南。
When I use Qt Designer, I want to view the corresponding python or c code(Form > View Code). However, the installed qt-designer cannot find uic module. I found the uic moudle(uic.exe) located in
C:Miniconda3Libsite-packagespyqt5_toolsuic.exe
and the pyuic5 executable (pyuic5.exe) located at
C:Miniconda3Scriptspyuic5.exe
In windows, we cannot create hard link, so I installed Hard Link Shell. Then I hard-linked those excutables to the path qt-designer used. Finally, it works like a charm.

