使用PyInstaller在-onefile

时间:2018-03-22 13:15:09

标签: python-3.x qml pyqt5 pyinstaller qtquick2

我想在Windows 10和Ubuntu中通过PyInstaller在PyQt5 GUI应用程序中使用QML(用于Material主题)构建一个可移植的可执行文件(至少是一个文件夹中的所有源文件)。但是,在成功构建可执行文件后,它会崩溃并显示一些错误消息。

material.py

import os
import sys

from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QUrl
from PyQt5.QtQml import QQmlApplicationEngine

if __name__ == "__main__":
    app = QApplication(sys.argv)
    os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material"
    engine = QQmlApplicationEngine()
    engine.load(QUrl('basic.qml'))
    sys.exit(app.exec_())

basic.qml :(从here复制)

import QtQuick 2.0
import QtQuick.Controls 2.1
import QtQuick.Controls.Material 2.1

ApplicationWindow {
    visible: true

    Material.theme: Material.Dark
    Material.accent: Material.Purple

    Column {
        anchors.centerIn: parent

        RadioButton { text: qsTr("Small") }
        RadioButton { text: qsTr("Medium");  checked: true }
        RadioButton { text: qsTr("Large") }
    }
}

我使用以下命令构建可执行文件:

pyinstaller ./material.py --onefile

构建后,可执行文件显示错误消息。在Windows 10中:

QQmlApplicationEngine failed to load component
file:///D:/test/dist/basic.qml:1 plugin cannot be loaded for module "QtQuick": Cannot load library D:\test\dist\QtQuick.2\qtquick2plugin.dll: ???????w?????C

在Linux中:

QQmlApplicationEngine failed to load component
file:///media/username/EA9E5E009E5DC5AB/test/dist/basic.qml:1 plugin cannot be loaded for module "QtQuick": Cannot load library /media/username/EA9E5E009E5DC5AB/test/dist/QtQuick.2/libqtquick2plugin.so: (/usr/lib/x86_64-linux-gnu/libQt5Quick.so.5: symbol _ZN3QV46Object11markObjectsEPNS_4Heap4BaseEPNS_15ExecutionEngineE, version Qt_5_PRIVATE_API not defined in file libQt5Qml.so.5 with link time reference)

项目的文件树是:

. (test)
+-- build
|   +-- (some files generate by PyInstaller)
+-- dist
|   +-- QtQuick (the folder copied from Python site-packages)
|   |   +-- (some files copied form Python site-packages)
|   +-- QtQuick.2 (the folder copied from Python site-packages)
|   |   +-- plugins.qmltypes
|   |   +-- qmldir
|   |   +-- qtquick2plugin.dll (or 'libqtquick2plugin.so' in Linux)
|   +-- basic.qml
|   +-- material.exe (or 'material' in Linux)
+-- basic.qml
+-- material.py
+-- material.spec

我复制了两个文件夹,QtQuickQtQuick.2,因为我对此question遇到了同样的问题,我和answer做同样的事情。我一直在寻找解决方案一周,没有线索为什么它无法加载库。

1 个答案:

答案 0 :(得分:1)

我发现使用Pyinstaller 3.3.1和PyQt5 >= 5.11可以解决此问题。

使用pyrcc5编译QML文件并将其导入Python脚本。因此,Pyinstaller会自动打包它们,而无需将QML文件放在可执行文件旁边。

在这种情况下,用basic.qml编译pyrcc5

pyrcc5 -o src.py src.qrc

然后,修改material.py

import os
import sys

from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QUrl
from PyQt5.QtQml import QQmlApplicationEngine
import src # import the resource file compiled by pyrcc5

if __name__ == "__main__":
    app = QApplication(sys.argv)
    os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material"
    engine = QQmlApplicationEngine()
    engine.load(QUrl('qrc:/basic.qml')) # modify the url for qrc format
    sys.exit(app.exec_())

最后,使用以下命令打包源代码。

pyinstaller material.py --windowed --onefile --hidden-import PyQt5.sip --hidden-import PyQt5.QtQuick

由于新版本的PyQt5修改了一些模块名称,从而使其与当前的Pyinstaller钩子不兼容,因此需要隐藏的导入。

但是,将代码打包后,结果发布二进制文件可能与QtQuick2样式显示有关(尤其是对于Material和Imagine主题)。您可以使用最新开发的Pyinstaller(3.4 dev)版本来解决此问题。