Create standalone applications using cx_Freeze

As we saw in the previous notebook, building standalone applications of simple programs is quite easy.

cx_Freeze analyses the program for required dependencies and packs everything into a folder together with a Python interpreter and an executable.

For more advanced programs however it can be a nightmare to get all required depedencies included.

Here is an example with PyQt4, Matplotlib and Numpy

1) Make the program

In this example, the program is a simple interactive python console.

It is written to the file "my_program.py" via the %%file cellmagic


In [5]:
%%file "my_qt_program.py"
import sys
from PyQt4 import QtGui
 
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
import matplotlib.pyplot as plt
import numpy as np
 
class QtWindow(QtGui.QDialog):
    def __init__(self, parent=None):
        QtGui.QDialog.__init__(self, parent)
        self.setWindowIcon(QIcon('test.ico'))
        self.figure = plt.figure()
        self.canvas = FigureCanvas(self.figure)
        self.button = QtGui.QPushButton('Plot')
        self.button.clicked.connect(self.plot)
        
        # set the layout
        layout = QtGui.QVBoxLayout()
        layout.addWidget(self.canvas)
        layout.addWidget(self.button)
        self.setLayout(layout)
 
    def plot(self):
        ''' plot some random stuff '''
        data = [np.random() for i in range(25)]
        ax = self.figure.add_subplot(111)
        ax.hold(False)
        ax.plot(data, '*-')
        self.canvas.draw()

    @staticmethod
    def run():
        app = QtGui.QApplication(sys.argv)
        main = QtWindow()
        main.show() 
        sys.exit(app.exec_())
if __name__ == '__main__':
    QtWindow.run()


Writing my_qt_program.py

In [3]:
from my_qt_program import QtWindow
QtWindow.run()


An exception has occurred, use %tb to see the full traceback.

SystemExit: 0
To exit: use 'exit', 'quit', or Ctrl-D.

2) Write a setup script


In [8]:
"""
Run this function if icons are not loaded
"""
from PyQt4 import QtCore
import sys
import os
app = QtCore.QCoreApplication(sys.argv)
qt_library_path = QtCore.QCoreApplication.libraryPaths()


imageformats_path = None
for path in qt_library_path:
    if os.path.exists(os.path.join(str(path), 'imageformats')):
        imageformats_path = os.path.join(str(path), 'imageformats')
        local_imageformats_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'imageformats')
        local_imageformats_path = os.path.join(os.getcwd(), 'imageformats')
        if not os.path.exists(local_imageformats_path):
            os.mkdir(local_imageformats_path)
        for file in glob.glob(os.path.join(imageformats_path, '*')):
            shutil.copy(file, os.path.join(local_imageformats_path, os.path.basename(file)))

In [6]:
%%file "setup.py"
    
from cx_Freeze import setup, Executable
import matplotlib
build_exe_options = {
    "includes" : ["sip", "matplotlib.backends.backend_tkagg"],
    
    "include_files": ['imageformats/', (matplotlib.get_data_path(), "mpl-data")]
}
setup(
name = "my_qt_program",
version="1.0.0",
options = { "build_exe": build_exe_options},
executables = [Executable("my_qt_program.py", base='Win32GUI', icon='test.ico')])


Overwriting setup.py

3) Build the application

To build the application open a console and run:

python setup.py build

Alternatively, run the cell below (output not shown) and wait until it returns (hopefully with a '0')


In [4]:
import os
print (os.system("python setup.py build"))


0

In [3]:
import build_cx_exe
from build_cx_exe import *
build_cx_exe.build_exe('my_qt_program.py', "1.0.0", modules=[PYQT4, SCIPY, MATPLOTLIB, NUMPY])


distribution created (my_qt_program_dist//)

Now the application is build. You can find it in "./build/exe.../my_qt_program.exe

MMPE's build_cx_exe

As inspiration you can have a look at build_cx_exe.py

It automates the process and is invoked by one line,

from build_cx_exe import build_exe, PYQT4, MATPLOTLIB, NUMPY
build_exe('my_qt_program.py', "1.0.0", modules=[PYQT4, MATPLOTLIB, NUMPY], icon='test.ico')

but it does only work on some systems, with some modules and cannot be used from ipython notebooks