PyInstaller и QML файлы - PullRequest
       31

PyInstaller и QML файлы

1 голос
/ 21 сентября 2019

Как я могу включить файл QML в мой проект Python как один исполняемый файл.Когда я запускаю pyinstaller --onefile main.py, запуск исполняемого файла приводит к ошибке, что файл QML не найден.Если я не использую абсолютный путь или не размещаю view.qml в том же каталоге, что и мой исполняемый файл.Я не хочу иметь отдельный файл QML, я хочу объединить его в исполняемый файл.

main.py:

if __name__ == "__main__":
  app = QGuiApplication(sys.argv)
  engine = QQmlApplicationEngine()
  engine.load(QUrl("view.qml"))
  sys.exit(app.exec_())

view.qml:

import QtQuick 2.0

ApplicationWindow {
  id: window
  title: "Window"
  width: 900
  height: 600
  visible: true
}

1 Ответ

1 голос
/ 21 сентября 2019

В моем ответе помимо того, что показано, как использовать возможный дубликат ответа в данном конкретном случае, также показана альтернатива с использованием собственных инструментов Qt.

1.Скопируйте .qml в ту же исполняемую папку

В этом случае вам необходимо построить абсолютный путь к qml, используя путь к приложению.

import os
import sys

from PySide2 import QtCore, QtGui, QtQml

# https://stackoverflow.com/a/404750/6622587
application_path = (
    os.path.dirname(sys.executable)
    if getattr(sys, "frozen", False)
    else os.path.dirname(os.path.abspath(__file__))
)


if __name__ == "__main__":
    import os
    import sys

    app = QtGui.QGuiApplication(sys.argv)
    engine = QtQml.QQmlApplicationEngine()
    file = os.path.join(application_path, "main.qml")
    engine.load(QtCore.QUrl.fromLocalFile(file))
    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec_())

Затем скопируйте .qmlв ту же исполняемую папку.

2.Добавьте .qml в качестве файлов данных

Файлы данных распаковываются в папку относительно sys._MEIPASS, если опция --onefile не используется, тогда этот путь являетсяв противном случае он будет распакован во временную папку.

В вашем случае он реализует следующее:

├── main.py
└── main.qml

main.py

import os
import sys

from PySide2 import QtCore, QtGui, QtQml

# https://stackoverflow.com/a/42615559/6622587
application_path = (
    sys._MEIPASS
    if getattr(sys, "frozen", False)
    else os.path.dirname(os.path.abspath(__file__))
)


if __name__ == "__main__":
    import os
    import sys

    app = QtGui.QGuiApplication(sys.argv)
    engine = QtQml.QQmlApplicationEngine()
    file = os.path.join(application_path, "main.qml")
    engine.load(QtCore.QUrl.fromLocalFile(file))
    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec_())

И запустите pyinstaller следующим образом:

pyinstaller --add-data "main.qml:." --onefile main.py

3.Используйте Qt Resource

Вы можете создать .qrc, который добавляет qml, затем конвертировать их в .py и, наконец, включить его в .py.

├── main.py
├── main.qml
└── qml.qrc

main.py

import sys

from PySide2 import QtCore, QtGui, QtQml

import qml_rc


if __name__ == "__main__":
    import os
    import sys

    app = QtGui.QGuiApplication(sys.argv)
    engine = QtQml.QQmlApplicationEngine()
    engine.load(":/main.qml")
    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec_())

qml.qrc

<RCC>
  <qresource prefix="/">
    <file>main.qml</file>
  </qresource>
</RCC>

Чтобы преобразовать qml.qrc в .py, необходимоиспользуйте следующую команду:

pyside2-rcc qml.qrc -o qml_rc.py 

и, наконец, поскольку это уже .py, мы запускаем только pyinstaller:

pyinstaller main.py --onefile
...