The scripts in this directory are for making new standalone releases. This is done using pyinstaller for all platforms.
This doesn't seem to work at present, follow the "more compact executable" instructions in the next section
First, install anaconda python 3.
Install pyinstaller from the developer branch (certain needed bug fixes are here only, as of 6/8/17, see this pyinstaller issue):
pip install git+https://github.com/pyinstaller/pyinstaller.git
You may be able to use conda pyinstaller:
conda install pyinstaller --channel conda-forge
Either way, you will need to monkey patch pyinstaller. Here is information on the issue:
https://stackoverflow.com/questions/63163027/how-to-use-pyinstaller-with-matplotlib-in-use
Here is more information on how to find the file that you need to edit:
>>> import PyInstaller
>>> PyInstaller.__file__
'/Users/***/anaconda3/envs/pmagpy_september_2020/lib/python3.7/site-packages/PyInstaller/__init__.py'
modify: /Users/***/anaconda3/envs/pmagpy_septempber_2020/lib/python3.7/site-packages/PyInstaller/hooks/hook-matplotlib.py
If you have a dll not loading error:
File "shapely/geos.py", line 112, in <module>
File "PyInstaller/loader/pyiboot01_bootstrap.py", line 146, in __init__.__main__.PyInstallerImportError: Failed to load dynlib/dll '/var/folders/qb/3td4bl3s2pz__jc94hp7z2c40000gn/T/_MEICSr2rH/lib/libgeos_c.dylib'. Most probably this dynlib/dll was not found when the application was frozen.
try commenting out line 112 and 113 from geos.py
The file is here:
~/anaconda3/envs/pmagpy_september)2020/lib/python3.7/site-packages/shapely/geos.py
Cartopy currently causes a seg fault and cannot be used (the executable will compile, but won't run). To fix this, I've prevented cartopy from being imported for the OSX executable. See commit fd5a710.
If you have a problem with MKL:
Install nomkl to prevent MKL problem (see this issue):
The supported Apple-silicon build uses PmagPy/pmag_gui_macos_arm64.spec.
Then run:
pyinstaller pmag_gui_macos_arm64.spec
This will create pmag_gui.app in PmagPy/dist. You can then move pmag_gui.app to PmagPy_Standalone_OSX, commit, and push it to Github. Make a new release on Github, and you're done!
5/29/2025: strictly refer to the pmag_gui_compile.yml environment file in this folder for the easiest way to reproduce a pyinstaller environment for compiling the standalone executable.
You can create an executable that is over 100MB smaller by installing a more minimal Python distribution using homebrew and pip. To do so, follow these steps:
-
Install brew
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
-
Install Python
brew install python
-
Link python3 --> python (not sure this is necessary)
ln -s /usr/local/bin/python3 /usr/local/bin/python
-
Use pip to install required packages
pip install matplotlib numpy scipy pandas
-
Use pip to install wxPython
pip install --upgrade -f https://wxpython.org/Phoenix/snapshot-builds/ wxPython
-
Use pip to install Pyinstaller
pip install git+https://github.com/pyinstaller/pyinstaller.git
-
Replace
#!/usr/bin/env/pythonwwith#!/usr/bin/env/python3at the top of pmag_gui.py magic_gui.py. -
Then you can generate a .spec file and run Pyinstaller, as explained above!
-
NB: to brew uninstall this python, you must first delete the symlink you created:
rm /usr/local/bin/pythonbrew uninstall python
Do not install cartopy. It is not required for creating standalones and breaks everything.
Same idea but with miniconda, (a stripped down version of Anaconda Python):
- Download miniconda for Python 3
- Install Python 3.5.1 # see: pyinstaller/pyinstaller#3192
conda install python=3.5.1
- Use conda to install required packages
conda install matplotlib numpy scipy pandas
- Use pip to install wxPython
pip install --upgrade --pre -f https://wxpython.org/Phoenix/snapshot-builds/ wxPython
- Use pip to install Pyinstaller
pip install git+https://github.com/pyinstaller/pyinstaller.git
- Upgrade setuptools
pip install setuptools --upgrade
- Then you can generate a .spec file and run Pyinstaller, as explained above!
The supported 64-bit Windows build uses PmagPy/pmag_gui_windows.spec. It is
separate from pmag_gui_macos_arm64.spec so each platform can enforce its own
architecture and packaging requirements.
Create the tested minimal environment from the repository root:
conda env create -f setup_scripts/pmag_gui_windows_compile.yml
conda activate pmag_gui_windows_compile
Then build the one-directory application:
pyinstaller --clean --noconfirm pmag_gui_windows.spec
The result is written to dist/pmag_gui_<version>_Windows/. Distribute the
entire directory (normally as a ZIP); the executable requires the adjacent
_internal directory. Cartopy is intentionally omitted from this lightweight
standalone environment and optional mapping functions remain unavailable in
the frozen application.
You can run the executable with output to Terminal (this is particularly useful when your build is refusing to launch):
./dist/pmag_gui_3.0
If this doesn't help, see the Pyinstaller troubleshooting guide.
The following command generates a starting spec file. Platform-specific settings must then be added and tested for the target operating system. Change directories into your PmagPy directory and run:
pyi-makespec --onefile --windowed --icon=.\programs\images\PmagPy.ico --name=PmagGUI .\programs\pmag_gui.py
Then add the following to the resulting spec file:
current_dir = os.getcwd()
files = [('{}/pmagpy/data_model/*.json'.format(current_dir), './pmagpy/data_model/'),
('{}/dialogs/help_files/*.html'.format(current_dir), './dialogs/help_files')
]
Additionally, in the Analysis function you will need to add the following arguments:
a = Analysis(['programs/pmag_gui.py'],
pathex=[current_dir],
binaries=[],
datas=files,
hiddenimports=['scipy.optimize', 'scipy.interpolate',
'scipy._lib.messagestream',
# timdeltas appears necessary for Windows with
# conda-installed pyinstaller
'pandas._libs.tslibs.timedeltas',
'pandas.concat', 'wget', 'pkg_resources.py2_warn'],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
That should do it!
If you want to include a version file as well, you can find more information here: an example can be found here and documentation here.
Made a new conda environment:
conda create -n make_executable2 python=3.6.6
Activated that conda environment:
conda activate make_executable2
Installed packages:
conda install matplotlib numpy scipy pandas
conda install wxpython
conda install pyinstaller
Compiled the program:
pyinstaller pmag_gui_macos_arm64.spec
Made a new conda enviroment
conda create -n pmag_gui_compile python=3.9.13
Activated that conda environment:
conda activate pmag_gui_compile
If numpy was installed by default in the new environment, remove mkl:
conda remove mkl
Install the nomkl package for numpy otherwise pyinstaller throws error:
conda install nomkl
conda install matplotlib numpy scipy pandas
-
Use pip to install wxPython
pip install --upgrade -f https://wxpython.org/Phoenix/snapshot-builds/ wxPython
-
Use pip to install Pyinstaller
pip install git+https://github.com/pyinstaller/pyinstaller.git
Compiled the program:
pyinstaller pmag_gui_macos_arm64.spec