0

Summary:

I developed a UI app with Pyside2 and it works when ran from Pycharm, but when I package it using PyInstaller the .exe doesnt read the .ui file included. It yields this error.

C:\Users\JULIAN~1.MIL\AppData\Local\Temp\_MEI6322\relevantUI.ui
QIODevice::read (QFile, "C:\Users\JULIAN~1.MIL\AppData\Local\Temp\_MEI6322\relevantUI.ui"): device not open
Designer: An error has occurred while reading the UI file at line 1, column 0: Premature end of document.
Traceback (most recent call last):
  File "relevantUI.py", line 84, in <module>
  File "relevantUI.py", line 49, in __init__
RuntimeError: Unable to open/read ui device
[19160] Failed to execute script relevantUI

The relevant code is this (im changing some naming for privacy purposes):

import PySide2
from PySide2 import QtXml
from PySide2.QtUiTools import QUiLoader
from PySide2.QtWidgets import QApplication, QWidget, QPushButton, QMessageBox, QComboBox
from PySide2.QtCore import QFile, QObject

import sys, os
import relevantClass

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)


class Form(QObject):

    def __init__(self, ui_file, parent= None):

        super(Form, self).__init__(parent)


        ui_file = QFile(ui_file)
        ui_file.open(QFile.ReadOnly)

        loader = QUiLoader()
        self.window = loader.load(ui_file)
        ui_file.close()

        btn_launch = self.window.Launch
        btn_upload = self.window.UploadFile
        btn_quit = self.window.Quit

        combo_map = self.window.MapComboBox
        combo_samples = self.window.SamplesComboBox


        btn_launch.clicked.connect(lambda: relevantClass.server_call(combo_map.currentIndex(),combo_samples.currentIndex()))
        btn_upload.clicked.connect(lambda: relevantClass.database_call(combo_map.currentIndex()))
        btn_quit.clicked.connect(self.quit_app)


        self.window.show()

    def quit_app(self):
        app.quit()

if __name__ == '__main__':

    # the path to the .ui is defined. We use resource_path to avoid absolute path problems using pyinstaller.
    filename = resource_path('relevantTemplateUI.ui')

    app = QApplication(sys.argv)
    form = Form(filename)
    sys.exit(app.exec_())

Then I call PyInstaller from install.py like follows:

import PyInstaller.__main__

PyInstaller.__main__.run([
    'relevantUI.py',
    '--onefile',
    #'--windowed',
    '--debug=all',
])

It creates the .exe but it yields the error quoted at the beginning.

Some comments.

  • Im installing from a script because using the auto_py_to_exe app has problems with global addresses, which are fixed with the function resource_path

  • I know, and I did, convert the original relevantTemplateUI.ui file to a .py file, but I encountered some very weird issues that are preventing me to use the file. For example this is the header of the converted .ui file:

    from PySide2.QtCore import * from PySide2.QtGui import * from PySide2.QtWidgets import *

    from pyside_test import Form

That pyside_test library is coming seemingly out of nowhere, i really dont know and it breaks the importing when using it inside relevantUI.py I can't simply comment it as in any case Form is instanced inside the class anyway. It is really weird, I really dont understand.

  • The relevantClass.py contains some subprocess routines, but those doesnt seem to be the problem, im pretty sure is related to Pyside2.

The question would be: how to make sure that PyInstaller is reading the .ui file device and package it correctly.

Note: just to be sure, relevantUI.py is the name of the main file of the app, the one I want to compile, relevantTemplateUI.ui is the file coming from QTDesigner, relevantClass.py is a class used by the app. Again, I need to change naming due privacy purposes.

eyllanesc
  • 221,139
  • 17
  • 121
  • 189

0 Answers0