Pyinstaller 独立可执行文件找不到规范文件中定义的 ui 文件

Posted

技术标签:

【中文标题】Pyinstaller 独立可执行文件找不到规范文件中定义的 ui 文件【英文标题】:Pyinstaller standalone executable cannot find ui file defined in spec file 【发布时间】:2020-05-19 09:03:43 【问题描述】:

我正在使用 pyinstaller 编译一个独立的可执行文件。 python 脚本使用来自 QtDesigner 的外部 ui 文件。如果没有 ui 文件,我无法让它运行可执行文件。我阅读了有关定义规范文件的信息,但是如果没有 ui 文件,我尝试的一切都不起作用。我不知道我做错了什么。我可以编译它,但是当我删除 ui 文件并运行可执行文件时,我得到了错误:

FileNotFoundError: [Errno 2] No such file or directory: 'D:/visu.ui'

如何将此文件集成到可执行文件中?

这是我的代码。使用pyi-makespec生成spec文件并手动添加数据:

visu.py

import sys
import os
from PyQt5 import QtWidgets, uic

def resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    try:
        # PyInstaller creates a temp folder and stores path in _MEIPASS
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")

    return os.path.join(base_path, relative_path)

Ui_MainWindow, QtBaseClass = uic.loadUiType(resource_path('visu.ui'))

class MyWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        Ui_MainWindow.__init__(self)
        self.setupUi(self)
if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = MyWindow()
    window.show()
    sys.exit(app.exec_())

visu.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Dialog</class>
 <widget class="QDialog" name="Dialog">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>172</width>
    <height>122</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Dialog</string>
  </property>
  <widget class="QPushButton" name="pushButton">
   <property name="geometry">
    <rect>
     <x>40</x>
     <y>50</y>
     <width>93</width>
     <height>28</height>
    </rect>
   </property>
   <property name="text">
    <string>Ok</string>
   </property>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

visu.spec

# -*- mode: python ; coding: utf-8 -*-

block_cipher = None


a = Analysis(['D:/visu.py'],
             pathex=['C:\\Users\\xxx'],
             binaries=[],
             datas=[("visu.ui", '.')],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          [],
          exclude_binaries=True,
          name='visu',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          console=True )
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=True,
               upx_exclude=[],
               name='visu')

【问题讨论】:

【参考方案1】:

我确定如果您将visu.ui 文件转换为visu.py

pyuic5 visu.ui -o visu.py 

那么你不会有任何问题。

pyinstaller -F -w pyinstaller_standalone_executable.py

pyinstaller_standalone_executable.py

import sys
import os
from PyQt5 import QtWidgets     #, uic

from visu import Ui_Dialog

'''
def resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """

    try:
        # PyInstaller creates a temp folder and stores path in _MEIPASS
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")

    return os.path.join(base_path, relative_path)

Ui_MainWindow, QtBaseClass = uic.loadUiType(resource_path('visu.ui'))
'''

#class MyWindow(QtWidgets.QMainWindow, Ui_MainWindow):
class MyWindow(QtWidgets.QDialog, Ui_Dialog):
    def __init__(self):
        super().__init__()

        self.setupUi(self)

        self.pushButton.clicked.connect(
            lambda: QtWidgets.QMessageBox.information(None, "Message", self.pushButton.text())
        )


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = MyWindow()
    window.show()
    sys.exit(app.exec_())

【讨论】:

以上是关于Pyinstaller 独立可执行文件找不到规范文件中定义的 ui 文件的主要内容,如果未能解决你的问题,请参考以下文章

使用 Pyinstaller 时找不到隐藏的导入 Tensorflow 包

PyInstaller 包烧瓶应用程序无法加载 Python 库,dlopen -> 找不到图像

Pyinstaller 找不到 opengl 的渲染器插件

Pyinstaller - 编译应用程序后找不到 libmagic

Pyinstaller 和 PyQt5 出错“找不到现有的 PyQt5 插件目录”

Pyinstaller - 独立的 .exe