I'm trying to export my .py script to .exe using PyInstaller, which has dependencies on .ui files which were created using Qt Designer.
I can confirm that my .py script works just fine when running it through PyCharm - I'm able to see the GUI I've created with the .ui files.
However, when I export my .py script to .exe and launch it, I recieve the following errors in the command line:
C:\Users\giranm>"C:\Users\giranm\PycharmProjects\PyQt Tutorial\dist\secSearch_demo.exe"
Traceback (most recent call last):
File "secSearch_demo.py", line 13, in <module>
File "site-packages\PyQt4\uic\__init__.py", line 208, in loadUiType
File "site-packages\PyQt4\uic\Compiler\compiler.py", line 140, in compileUi
File "site-packages\PyQt4\uic\uiparser.py", line 974, in parse
File "xml\etree\ElementTree.py", line 1186, in parse
File "xml\etree\ElementTree.py", line 587, in parse
FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\giranm\\securitySearchForm.ui'
Failed to execute script secSearch_demo
For some reason, the .exe file is looking for the .ui file within the path - C:\Users\giranm\
However, having done some research already, I was told that I needed to use os.getcwd() and ensure that I have the full path in my script. Even with the code below, I still get errors trying to locate the .ui files.
PyInstaller: IOError: [Errno 2] No such file or directory:
# import relevant modules etc...
cwd = os.getcwd()
securitySearchForm = os.path.join(cwd, "securitySearchForm.ui")
popboxForm = os.path.join(cwd, "popbox.ui")
Ui_MainWindow, QtBaseClass = uic.loadUiType(securitySearchForm)
Ui_PopBox, QtSubClass = uic.loadUiType(popboxForm)
# remainder of code below.
I'm aware that one can convert .ui files to .py and import them into the main routine using pyuic4. However, I will be making multiple edits to the .ui files
and thus it is not feasible for me to keep converting them.
Is there anyway to fix this so that I can create a standalone .exe?
I'm fairly new to using PyQT4 and PyInstaller - any help would be much appreciated!
After scratching my head all weekend and looking further on SO, I managed to compile the standalone .exe as expected using the UI files.
Firstly, I defined the following function using this answer
Bundling data files with PyInstaller (--onefile)
# Define function to import external files when using PyInstaller.
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)
Next I imported the .UI files using this function and variables for the required classes.
# Import .ui forms for the GUI using function resource_path()
securitySearchForm = resource_path("securitySearchForm.ui")
popboxForm = resource_path("popbox.ui")
Ui_MainWindow, QtBaseClass = uic.loadUiType(securitySearchForm)
Ui_PopBox, QtSubClass = uic.loadUiType(popboxForm)
I then had to create a resource file (.qrc) using Qt Designer and embed images/icons using this resource file. Once done, I used pyrcc4 to convert the .qrc file to .py file, which would be imported in the main script.
Terminal
C:\Users\giranm\PycharmProjects\PyQt Tutorial>pyrcc4 -py3 resources.qrc -o resources_rc.py
Python
import resources_rc
Once I have confirmed the main .py script works, I then created a .spec file using PyInstaller.
Terminal
C:\Users\giranm\PycharmProjects\PyQt Tutorial>pyi-makespec --noconsole --onefile secSearch_demo.py
As per PyInstaller's guide, I've added data files by modifying the above .spec file.
https://pythonhosted.org/PyInstaller/spec-files.html#adding-data-files
Finally, I then compiled the .exe using the .spec file from above.
You can simply use:
uic.loadUi(r'E:\Development\Python\your_ui.ui', self)
Use the full path, and use pyinstaller with standard arguments, and it works fine. The r prefix makes sure the backslashes are interpreted literally.
Another method, tested on Ubuntu 20.04 is to add the .ui file to the data section in the spec file. First generate a spec file with pyinstaller --onefile hello.py. Then update the spec file and run pyinstaller hello.spec.
a = Analysis(['hello.py'],
...
datas=[('mainwindow.ui', '.')],
...
The next step is to update the current directory in your Python file. To do this, the os.chdir(sys._MEIPASS) command has to be used. Wrap it in a try-catch for development use when _MEIPASS is not set.
import os
import sys
# Needed for Wayland applications
os.environ["QT_QPA_PLATFORM"] = "xcb"
# Change the current dir to the temporary one created by PyInstaller
try:
os.chdir(sys._MEIPASS)
print(sys._MEIPASS)
except:
pass
from PySide2.QtUiTools import QUiLoader
from PySide2.QtWidgets import QApplication
from PySide2.QtCore import QFile, QIODevice
if __name__ == "__main__":
app = QApplication(sys.argv)
ui_file_name = "mainwindow.ui"
ui_file = QFile(ui_file_name)
if not ui_file.open(QIODevice.ReadOnly):
print(f"Cannot open {ui_file_name}: {ui_file.errorString()}")
sys.exit(-1)
loader = QUiLoader()
window = loader.load(ui_file)
ui_file.close()
if not window:
print(loader.errorString())
sys.exit(-1)
window.show()
sys.exit(app.exec_())
I am using pyinstaller to compile a python script to an exe, but before I do that I want to obfuscate it using pyarmor, I fired up pyarmor web ui using pyarmor-webui and created a build that gives out a file named the same one as the file I want to compile but obfuscated and a folder containing two files __init__.py and _pytransform.dll now when I try to compile the obfuscated code into an exe using pyinstaller --onefile myfile.py I get an executable that when I run from a batchfile to look at the output it throws the following error Could not find "C:\Users\0000\AppData\Local\Temp\_MEI72482\pytransform\platforms\windows\x86_64\_pytransform.dll"
myfile.py
import os
import random
for i in range (10):
print (random.randrange(1,100))
Batch file
try_01.exe
pause
How and what do I need to add to pyinstaller command so that it includes the .dll file in the compilation process
The pyinstaller docs say the following:
--add-binary <SRC;DEST or SRC:DEST>
Additional binary files to be added to the executable. See the --add-data option for more details. This option can be used multiple times.
I haven't used pyarmor+pyinstaller before but it should be as simple as:
pyinstaller --onefile myfile.py --add-binary _pytransform.dll
Or, since I looked more into pyarmor's output, it may be:
pyinstaller --onefile myfile.py _pytransform.dll
Executable made with pyInstaller / UPX in virtual environment throws an error
DLL load failed: The parameter is incorrect. while parameter is correct...
I've made python Executable withoutpyInstaller UPX Its about 250MB & Its working Fine.
To reduce size I've created another python Executable (Contains Same Code) Using pyInstaller UPX and its gives me an error refer Error_img.
Code Contains libraries like Pandas,Numpy,Openpyxl
The error is showing at line 8 where I've defined Pandas library
I came up with the solution and It's working perfectly Fine...
Need to add Pandas and Numpy Manually using pyinstaller --add-data option
pyinstaller --add-data C:\ve\mypython\Lib\site-packages\pandas;pandas --add-data C:\ve\mypython\Lib\site-packages\numpy;numpy --icon=icon_file.ico --version-file version.txt --noconsole --upx-dir=C:\upx --upx-exclude vcruntime140.dll --upx-exclude ucrtbase.dll --onefile Foo.py
After creating Executable the size of an EXE is 170MB.
the --add-data option works well without using --onefile option
I want the data text files to be compressed and merged into an exe file. But exe file only works when the data text file is in the same folder.
How can I merge the text file into the only one exe file??
When I used:
pyinstaller --add-data ="\GameUserSettings.ini;." file.py
it works.
pyinstaller --onefile --add-data ="\GameUserSettings.ini;." file.py
it can make the file.exe but it doesn't work well. and it works only when the text file is in the same folder.
When you add your text file with one-dir, Pyinstaller would put your file next to your executable and you will be fine when accessing your file by the script (e.g open("myfile.txt"). But when you create your executable with --onefile it would extract your file in a temp directory which is a separate directory, so calling open("myfile.txt") would result in a NotFound error because the file doesn't exist besides your executable. So you need to change the path to point to the temp directory. The sys._MEIPASS would return the temp directory so you need to locate your files inside it. You can find more info in here.
A function like this would solve the problem:
import sys
import os
def resource_path(relative_path):
if hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath("."), relative_path)
Then you can access your file with source = resource_path("myfile.txt").
I am trying to create a .exe file from my Python file. My setup file contains the following code (which was generated using the PyBuilder application):
# setup.py
from distutils.core import setup
import py2exe
import sys
sys.stdout = open('screen.txt','w')
sys.stderr = open('errors.txt','w')
setup(name='Crypto Calculator',
version='1.0',
author='RedCode',
data_files=[],
windows=[{'script':'Crypto Calculator.py',
'icon_resources':[(1,'')],
}])
print("---Done---")
When I run the command pyinstaller setup.pyw I get the IndexError: tuple out of range error. When I try running the pyinstaller command on my actual application's file, it still gives me the same error.
How can I correct this problem and successfully create a Python exe file.