To instruct PyInstaller how to build Luxocator, we must create a specification file, which we will call Luxocator.spec
. Actually, the specification file is a Python script that uses a PyInstaller class called Analysis
and PyInstaller functions called PYZ
, EXE
, and BUNDLE
. The Analysis
class is responsible for analyzing one or more Python scripts (in our case, just Luxocator.py
) and tracing all the dependencies that must be bundled with these scripts in order to make a redistributable application. Sometimes, Analysis
makes mistakes or omissions, so we will modify the list of dependencies after it is initialized. Then, we will zip the scripts, make an executable, and make an app bundle using PYZ
, EXE
, and BUNDLE
, respectively. Here is the implementation:
import os a = Analysis(['Luxocator.py'], pathex=['.'], hiddenimports=[], hookspath=None, runtime_hooks=None) # Determine the platform. platform = os.name if platform == 'nt': # We are on Windows. # A bug causes the 'pyconfig' module to be included twice. # Remove the duplicate. for data in a.datas: if 'pyconfig' in data[0]: a.datas.remove(data) break # Include SSL certificates for the sake of the 'requests' module. a.datas.append(('cacert.pem', 'cacert.pem', 'DATA')) # Include our app's classifier data. a.datas.append(('classifier.mat', 'classifier.mat', 'DATA')) pyz = PYZ(a.pure) exe = EXE(pyz, a.scripts, a.binaries, a.zipfiles, a.datas, name='Luxocator', icon='win\icon-windowed.ico', debug=False, strip=None, upx=True, console=False ) app = BUNDLE(exe, name='Luxocator.app', icon=None)
Note that this script specifies three resource files that must be bundled with the app: cacert.pem
, classifier.mat
, and win\icon-windowed.ico
. We have already discussed cacert.pem
in the previous section and classifier.mat
is the output of our main function in HistogramClassifier.py
. The Windows icon file, win\icon-windowed.ico
, is included in this chapter's code bundle, which is downloadable from my website at http://nummist.com/opencv/7376_02.zip. Alternatively, you can provide your own icon file if you prefer.
For more information about PyInstaller's Analysis class, specification files, and other functionality, see the official documentation at http://pythonhosted.org/PyInstaller/.
Now, let's write a platform-specific shell script to clean any old builds, train our classifier, and then bundle the app using PyInstaller. On Windows, create a script called build.bat
, which contains the following commands:
set PYINSTALLER=C:\PyInstaller\pyinstaller.py REM Remove any previous build of the app. rmdir build /s /q rmdir dist /s /q REM Train the classifier. python HistogramClassifier.py REM Build the app. python "%PYINSTALLER%" Luxocator.spec REM Make the app an executable. rename dist\Luxocator Luxocator.exe
Similarly, on Mac or Linux, create a script called build.sh
. Make it executable (for example, by running $ chmod +x build.sh
in Terminal). The file should contain the following commands:
#!/bin/sh PYINSTALLER=~/PyInstaller/pyinstaller.py # Remove any previous build of the app. rm -rf build rm -rf dist # Train the classifier. python HistogramClassifier.py # Build the app. python "$PYINSTALLER" Luxocator.spec # Determine the platform. platform=`uname -s` if [ "$platform" = 'Darwin' ]; then # We are on Mac. # Copy custom metadata and resources into the app bundle. cp -r mac/Contents dist/Luxocator.app fi
Note that on Mac (the 'Darwin'
platform), we are manually modifying the app bundle's contents as a post-build step. We do this in order to overwrite the default app icon and default properties file that PyInstaller puts in all Mac apps. (Notably, the default properties do not include support for the Retina mode, so they make the app look pixelated on recent Mac hardware. Our customizations fix this issue.) This chapter's code bundle, which is downloadable from my website at http://nummist.com/opencv/7376_02.zip, includes the custom Mac app contents in a folder called mac/Contents
. You can modify its files to provide any icon and properties you want.
After running the platform-specific build script, we should have a redistributable build of Luxocator at dist/Luxocator.exe
(in Windows), dist/Luxocator.app
(in Mac), or dist/Luxocator
(in Linux). If we are using 64-bit Python libraries on our development machine, this build will only work on 64-bit systems. Otherwise, it should work on both 32-bit and 64-bit systems. The best test of the build is to run it on another machine that does not have any of the relevant libraries (such as OpenCV) installed.