python pyinstaller create single file import directory - python

i have used pyinstaller to create a single .exe for windows using a single .py file and it worked fine. now i have gotten a bit more complex and have created multiple .py files stored in folders beneath my main.py. i've read through the pyinstaller guides , yet something doesn't seem to be working on my part..
my folder structure in windows is as follows, i'm just using a simple example for illustration :
app_root\main.py
app_root\__init__.py
\library\__init__.py
\library\app_ext1.py
\library\app_ext2.py
\library\test\__init__.py
\library\test\app3.py
in main.py i am importing code from
from library.app_ext1 import get_info
from library.app_ext2 import get_data
from library.test.app3 import get_test
so i run pyinstaller to my main.py using my .spec file.
in the .spec file i have
hiddenimports=['library']
pyinstaller finishes no errors and creates my single .exe, but when i run my single .exe i get the following error
C:\Users\user1\Desktop\1_file\dist>main.exe
Traceback (most recent call last):
File "app_root\main.py", line 2, in <module>
ImportError: No module named 'library'
Failed to execute script main
i wrote a test script just using a single .py file and it was doing some simple work with openpyxl (a python excel library) so in my test .py file i had "import openpyxl" , so in my spec file i used
hiddenimports=['openpyxl']
that worked fine but openpyxl is python lib that was installed using pip , i guess i'm not fully understanding how to import my own modules/scripts that i have created and stored in a folder structure beneath my main .py script file that i'm referencing between my .py script files as in my example above.
how can i make pyinstaller recognize my .py scripts i'm importing?

ok not sure why , but i just created a new folder in windows , copied all my .py files using same folder structure as before and then it worked. the only thing missing was all the Pycharm folders like .git, .idea, and pycache
i did notice in troubleshooting that if i renamed library to something else like "test" and updated my import lines it would still reference module "library" when i executed the .exe that was built.
i knew i was doing all this correctly but seems there might have been something in one of the other folders that py charm puts in there.
so i am just going to copy all my files to new folder each time and delete any folders/files i see other than the .py required.

In my case I replaced from library.app_ext1 import get_info to from your_newly_created_folder_name.library.app_ext1 and it worked :D
I noticed app_root name must be changed with new created folder name. just created a new folder, copy all .py files and keep folder structure. I hope you no one else will waste his time like me on this anymore

Related

How to pack a python to exe while keeping .py source code editable?

I am creating a python script that should modify itself and be portable.
I can achieve each one of those goals separately, but not together.
I use cx_freeze or pyinstaller to pack my .py to exe, so it's portable; but then I have a lot of .pyc compiled files and I can't edit my .py file from the software itself.
Is there a way to keep a script portable and lightweight (so a 70mb portable python environment is not an option) but still editable?
The idea is to have a sort of exe "interpreter" like python.exe but with all the libraries linked, as pyinstaller allows, that runs the .py file, so the .py script can edit itself or be edited by other scripts and still be executed with the interpreter.
First define your main script (cannot be changed) main_script.py. In a subfolder (e.g. named data) create patch_script.py
main_script.py:
import sys
sys.path.append('./data')
import patch_script
inside the subfolder:
data\patch_script.py:
print('This is the original file')
In the root folder create a spec file e.g. by running pyinstaller main_script.py.
Inside the spec file, add the patch script as a data resource:
...
datas=[('./data/patch_script.py', 'data' ) ],
...
Run pyinstaller main_sript.spec. Execute the exe file, it should print
This is the original file
Edit the patch script to e.g. say:
print('This is the patched file')
Rerun the exe file, it should print
This is the patched file
Note: As this is a PoC, this works but is prone to security issues, as the python file inside the data directory can be used for injection of arbitrary code (which you don't have any control of). You might want to consider using proper packages and update scripts as used by PIP etc.

Including excel files with program in Pyinstaller

I have written code in python which opens up a template excel file. Everyday, a midnight, it copies that template into a new excel file where the code will record data into it for that day. My goal is to create a single executable file containing my code AND the template excel file using pyinstaller.
Basically I want to be able to open the template excel file regardless of whether the computer contains the file or not by bundling the excel file into the exe file obtained from pyinstaller:
Right now I open the excel file as shown below:
import os
import openpyxl
theFile = openpyxl.load_workbook(os.getcwd()+"\templateExcel.xlsx")
currentSheet = theFile[theFile.sheetnames[0]]
However, when I include the excel file to the pyinstaller command as --add-data "templateExcel.xlsx;templateExcel.xlsx, and run the exe file, it is not able to detect the location of the templateExcel file. I understand that by running on a different computer, the os.getcwd() gives a different path so it would obviously not be able to open the excel file. Hence I needed a way to bundle the excel file into the exe file such that the python code can find it regardless of the computer.
You can use;
Adding a data file in Pyinstaller using the onefile option
Summarly:
pyinstaller --onefile --nowindow --add-data text.txt;included winprint.py --distpath .
and sample python script:
import os
import sys
os.chdir(sys._MEIPASS)
os.system('included\\text.txt')
Please note:
When using "getcwd()" you won't receive the desired outcome you were looking for, it will get you the place from which you have executed your exe file.
For example, look at the following long module:
from os import getcwd
print(getcwd())
If you execute it from different locations, you will get different results:
Had PyInstaller worked like you assume it would (placing the file relative to some module) you could have used file instead of getcwd() as it indicated where the module resides (which is constant, unlike the location from which the exe is executed), but it doesn't.
Any way, #Sezer BOZKIR's answer should suffice, note the comment I added there.

I'm getting this error when I'm trying to make an .exe file through pyinstaller - "ModuleNotFoundError: No module named 'acrcloud_extr_tool'"

Im using ACRCloud to recognize an audio file, I've build a GUI using tkinter and I'm freezing the code as an .exe file using PyInstaller. However, I'm getting this error when I'm running the .exe file:
ModuleNotFoundError: No module named 'acrcloud_extr_tool'
If I run it directly from the script, there's no error and it runs fine. Some help, please? I'm just starting out.
From my experience using pyinstaller, I need to add a parameter to the build command, so that pyinstaller knows where to look for modules. If you are building from a command prompt, the line may read something like this:
pyinstaller "yourFileName.py"
However, you can add other commands to this that specify how the exe is built - whether it has a custom icon, is console based or the console is hidden, etc. Additionally, you can add a list of paths, telling pyinstaller where to look for your modules and that's done like this:
pyinstaller -p C:\theFolderWhereYourCustomModulesAreSaved:C:\Users\yourName\AppData\Local\Programs\Python\Python36-32\Lib\site-packages "yourFileName.py"
Notice there are no quotation marks around these file paths AND that they are separated by a colon. The path to your Python site packages may be a bit different than mine, but I left in all the same path info with the exception of my username, so edit that as needed for your own machine. Also, the first 'fake' path I have shown in the example would be if you have written some of your own modules and are importing them into your project. For example, if your main project is saved in C:\myProject but you have modules you've written that are imported into your program like this:
import myCustomModule
and THOSE modules are saved in C:\myProject\myModules, then you would change that command to look like this:
pyinstaller -p C:\myProject\myModules:C:\Users\yourName\AppData\Local\Programs\Python\Python36-32\Lib\site-packages "yourFileName.py"
Hopefully this solves your problem.
I solved it. Turns out due to it being a binary file (of .pyd extension), it had to be added explicitly in the .spec file (read the pyinstaller documentation). I did it and it ran like a charm.

How to get pyinstaller to include imported .py files

I have a GUI script, called ui.py, created in PySide that uses functions from another script, called DataFunctions.py. When I run the ui.py file in python it all works perfectly, and when I run the ui.exe file it will all work fine apart from the button that runs the DataFunctions.py file, which does nothing.
In my ui.py file I am importing DataFunctions.py with:
import DataFunctions.py
buttonAction = DataFunctions.writeFile(filename, data)
I am using the following code to create the .exe:
pyinstaller ui.py -w -F
Am I importing the DataFunctions.py file in a way that pyinstaller doesn't support?
Drop the .py extension in the import line
import Datafunctions
Make sure the Datafunctions.py code is in the same folder.
It turns out that the DataFunctions.py file was included in the .exe, however some file paths relative to the DataFunctions.py file inside it were not set correctly due to the .exe being created in another folder. If anyone else is having similar problems, make sure you don't specify -w so that you can use the console to debug your .exe. Look here for how to find the location of the .exe file when it is run.

Using pyinstaller to make standalone file on Mac

I'm trying to use pyinstaller with python version 2.7 to make a standalone file that will run a small app I made using tkinter, but I'm having trouble following the documentation. I found this, but it's for python 2.5 and windows
http://www.pyinstaller.org/export/v2.0/project/doc/Manual.html?format=raw#spec-files
I made two folders on my desktop, one for pyinstaller and one containing my files.
In terminal I changed the directory to the pyinstaller folder. Then I typed the following:
python pyinstaller.py /Users/.../Desktop/BuildFolder/menu.py
//buildfolder contains my files, menu.py is the file I run to start the app
When this runs, I get a message staing something along the lines of "The output directory and all of its contents will be removed. Proceed y/n?" Upon selecing yes, It then creates the directory
/Users/.../Desktop/pyinstaller-2.0/menu
Inside that menu folder, there's a .SPEC file. So, I run the following in terminal
python pyinstaller.py /Users/.../Desktop/BuildFolder/menu/menu.spec
After this runs, I found a .PKG file in that folder but it's not labeled anything like menu.py . I can't figure out what to do next, and I'm not sure if I'm supposed to run other files.
I am not sure ( haven't tried this yet ), but maybe you have to run Build.py while working with .SPEC file?

Categories

Resources