Adding textfile with --onefile option - python-3.x

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").

Related

configparser.NosectionError found when run a .exe generated from pycharm (Python)

I have created an exe file from pycharm using pyinstaller --onefile -w ./workflow/Workflow3.py
I have my config.ini located under folder resources.
i have used
config = configparser.ConfigParser()
# Read in config.ini from a path
config.read('../resources/config.ini')
ALternatively i have used all the possible combinations like absolute path. But i am getting below error when i directly run .exe.At the same time its working in pycharm

Pyinstaller bundled exe not working, but folder exe does [duplicate]

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_())

How to include files while compiling?

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

How can I decompile an exe file I made with Pyinstaller?

I made a .py file and was looking how to convert it into an .exe file. I found pyinstaller and while messing around with it I was able to create a basic exe file with pyinstaller. The problem is that I didnt have a copy of my .py file as backup because I'm a beginner and now I can't look at my source code. Is there a way for me to decompile the pyinstaller files to attempt to recover some of my code?
My .py file was created in python 3.8 if that is relevant

pyinstaller and --onefile: excluding a .py file

I have an application that I distribute using pyinstaller with the --onefile flag so that it is neater (even though unpacking it takes a bit of time).
I would like to leave a function accessible to the end user in a file called, say, user.py. If I run pyinstaller with --onefile and --exclude-module user, the resulting executable doesn't seem to be able to run my local copy of user.py.
Is this possible?
I didn't get any traction on this question, so I figured I'd add some more detail.
Eg. I made three files:
main.py
try:
from otherfile import getresponse
except ImportError:
from packagedfile import getresponse
resp = getresponse()
print(resp)
packagedfile.py
def getresponse():
return "Response in packaged file"
otherfile.py
def getresponse():
return "Response in other file"
When I run this (python main.py) with all three files in the same dir, it prints response in other file. When I compile with pyinstaller (pyinstaller main.py) I get the same response. When I compile with pyinstaller as pyinstaller --exclude-module otherfile main.py and put otherfile.py in the same directory, I get the same response. When I compile with pyinstaller as pyinstaller --exclude-module otherfile --onefile main.py, I get 'Response in packaged file' when otherfile.py is in the same directory as the .exe file.
You can try:
pyinstaller --exclude-module otherfile --add-data otherfile;. main.py

Resources