I build a simple GUI using Tkinter which I would like to freeze to a standalone executable. I am doing this inside a conda environment. Working with OSX 10.15.7, python 3.7, PyInstaller 4.5.1 and conda 4.10.0. The folder structure looks like this (simplified):
- ImSep_files
| - ai4eutils
| - ImSep
| | - ImSep_GUI.py
| - cameratraps
| - detection
| - run_tf_detector.py
The script calls other scripts in the ai4eutils and cameratraps folders. If I create a conda env, set the PYTHONPATH
to include the paths to ai4eutils
and cameratraps
, and run python ImSep_GUI.py
, there is no problem. The GUI opens and functions perfectly. However, if I do exactly the same but run pyinstaller
instead of python
, it creates an exe which opens the GUI but throws an error when a button is pressed.
File "/Users/peter/Applications/ImSep_files/cameratraps/detection/run_tf_detector_batch.py", line 56, in <module>
from detection.run_tf_detector import ImagePathUtils, TFDetector
ModuleNotFoundError: No module named 'detection.run_tf_detector'
This means that pyinstaller
cannot find the run_tf_detector.py
file. I have tried adding the --paths
flag like:
pyinstaller --onefile --windowed --name='ImSep' --icon='imgs/logo_small_bg.icns' --paths=/Users/peter/Applications/ImSep_files --paths=/Users/peter/Applications/ImSep_files/ai4eutils --paths=/Users/peter/Applications/ImSep_files/cameratraps --paths=/Users/peter/Applications/ImSep_files/cameratraps/detection ImSep_GUI.py
I am aware that there are many topics about this type or error. I have tried many potential solutions, but none seem to work. I have tried the following:
- Using the
--hidden-import
flag, as suggested here by HHest. If tried different versions:--hidden-import detection.run_tf_detector
,--hidden-import cameratraps.detection.run_tf_detector
,--hidden-import cameratraps.detection
, etc. - Adjusting the
hiddenimports=[],
line with the above paths, as suggested here by user1251007. - Adding
sys.path.append(path/to/run_tf_detector.py)
to the top ofImSep_GUI.py
. - Downgrading
pyinstaller
to 3.1, as suggested here by fivef. - Creating a
hook.py
withdetection.run_tf_detector
the in ahooks
folder and adding it as--additional-hooks-dir=hooks
, as suggested here by Legorooj. - Loading the needed module as data in the spec file, as suggested here by Ken4scholars.
- Copy
run_tf_detector.py
into the file folder the same level ofImSep.exe
, as suggested here by Wayne Zhang. - Call
pyinstaller
from parent directory, as suggested here by all or None. - Install
pyinstaller
in the same directory in whichImSep_GUI.py
is present, as suggested here by Habeeb Rahman K T. - Install
pyinstaller
usingconda-forge
instead ofpip
, as suggested here by piping piping.
FYI, this is how I create the environment and run pyinstaller
:
conda create --name imsepcondaenv python=3.7 -y
conda activate imsepcondaenv
pip install tensorflow==1.14 pillow==8.4.0 humanfriendly==10.0 matplotlib==3.4.3 tqdm==4.62.3 jsonpickle==2.0.0 statistics==1.0.3.5 requests==2.26.0
conda install -c conda-forge pyinstaller -y
cd ~/Applications/ImSep_files
export PYTHONPATH="$PYTHONPATH:$PWD/ai4eutils:$PWD/cameratraps"
cd ImSep
pyinstaller --onefile --windowed --name='ImSep' --icon='imgs/logo_small_bg.icns' --paths=/Users/peter/Applications/ImSep_files --paths=/Users/peter/Applications/ImSep_files/ai4eutils --paths=/Users/peter/Applications/ImSep_files/cameratraps --paths=/Users/peter/Applications/ImSep_files/cameratraps/detection ImSep_GUI.py
Does anyone have an idea of what I'm doing wrong?
PS: For OSX and UNIX users it is possible to get a reproducible example:
mkdir ImSep_files
cd ImSep_files
git clone https://github.com/Microsoft/cameratraps -b tf1-compat
git clone https://github.com/Microsoft/ai4eutils
git clone https://github.com/PetervanLunteren/ImSep.git
curl --output md_v4.1.0.pb https://lilablobssc.blob.core.windows.net/models/camera_traps/megadetector/md_v4.1.0/md_v4.1.0.pb