Using cx_freeze to freeze your application

The following will explain how to freeze a Python/wxPython application using the cx_freeze tool.

What Objects are Involved

You will need a working development environment including

* Python

* wxPython

* cx_freeze

* Gui2Exe - by Andrea Gavana

Process Overview

A small sample wxPython "Hello world" application will be used to demonstrate the process. I created the tiny application using Boa Constructor but you could use any other IDE you use for your wxPython development. I did the initial creation of the setup.py file with Gui2Exe and then keep maintaining it and running it from the IDE (Boa in my case).

Special Concerns

Python 2.5x

Python 2.6x

The setup.py

Save the following code in your working folder as a file called 'setup.py'.

I selected the "Compressed" option which created two .zip files to reduce the number of files to distribute, it also automagically copied the required dll's needed by Python and wxPython into the "dist" folder.

To deliver a single file to your end-users check out the InnoSetup page.

To "freeze" the application you run the following command from the command line in your working folder.

\python26\python setup.py build

   1 # Let's start with some default (for me) imports...
   2 
   3 from cx_Freeze import setup, Executable
   4 
   5 
   6 
   7 # Process the includes, excludes and packages first
   8 
   9 includes = []
  10 excludes = ['_gtkagg', '_tkagg', 'bsddb', 'curses', 'email', 'pywin.debugger',
  11             'pywin.debugger.dbgcon', 'pywin.dialogs', 'tcl',
  12             'Tkconstants', 'Tkinter']
  13 packages = []
  14 path = []
  15 
  16 # This is a place where the user custom code may go. You can do almost
  17 # whatever you want, even modify the data_files, includes and friends
  18 # here as long as they have the same variable name that the setup call
  19 # below is expecting.
  20 
  21 # No custom code added
  22 
  23 # The setup for cx_Freeze is different from py2exe. Here I am going to
  24 # use the Python class Executable from cx_Freeze
  25 
  26 
  27 GUI2Exe_Target_1 = Executable(
  28     # what to build
  29     script = "simplewx.py",
  30     initScript = None,
  31     base = 'Win32GUI',
  32     targetDir = r"dist",
  33     targetName = "simplewx.exe",
  34     compress = True,
  35     copyDependentFiles = True,
  36     appendScriptToExe = False,
  37     appendScriptToLibrary = False,
  38     icon = None
  39     )
  40 
  41 
  42 # That's serious now: we have all (or almost all) the options cx_Freeze
  43 # supports. I put them all even if some of them are usually defaulted
  44 # and not used. Some of them I didn't even know about.
  45 
  46 setup(
  47     
  48     version = "0.1",
  49     description = "No Description",
  50     author = "No Author",
  51     name = "cx_Freeze Sample File",
  52     
  53     options = {"build_exe": {"includes": includes,
  54                              "excludes": excludes,
  55                              "packages": packages,
  56                              "path": path
  57                              }
  58                },
  59                            
  60     executables = [GUI2Exe_Target_1]
  61     )
  62 
  63 # This is a place where any post-compile code may go.
  64 # You can add as much code as you want, which can be used, for example,
  65 # to clean up your folders or to do some particular post-compilation
  66 # actions.
  67 
  68 # No post-compilation code added
  69 
  70 
  71 # And we are done. That's a setup script :-D

The MS manifest

Following is the content of the Microsoft manifest file ("Microsoft.VC90.CRT.manifest"), note that the content of "version" and "publicKeyToken" are specific to the version of the dll files.

Installing Python 2.6 on Windows with the option "for this user only" this manifest file is created in the Python26 folder, note the Py26 installer does not offer the "for this user only" option on Vista.

If you install Python 2.6 for all users then these files are found in "C:\Windows\winsxs", i.e. in "C:\Windows\winsxs\Manifests" you will find guess what the manifest and it would be called "x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.21022.8_none_bcb86ed6ac711f91.manifest" and then in "C:\Windows\winsxs\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.21022.8_none_bcb86ed6ac711f91" you will find the dll's.

Note that the folder names contain the version number, so with Python 2.6.2 you should use version 9.0.21022.8 manifest and dll's.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Copyright (c) Microsoft Corporation.  All rights reserved. -->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <noInheritable/>
    <assemblyIdentity
        type="win32"
        name="Microsoft.VC90.CRT"
        version="9.0.21022.8"
        processorArchitecture="x86"
        publicKeyToken="1fc8b3b9a1e18e3b"
    />
    <file name="msvcr90.dll" /> <file name="msvcp90.dll" /> <file name="msvcm90.dll" />
</assembly>

Sample wxPython application

Save the following code in your working folder as a file called 'simplewx.py'.

   1 #Boa:Frame:Frame1
   2 
   3 import wx
   4 
   5 def create(parent):
   6     return Frame1(parent)
   7 
   8 [wxID_FRAME1, wxID_FRAME1BUTTON1, wxID_FRAME1BUTTON2, wxID_FRAME1PANEL1, 
   9  wxID_FRAME1STATICTEXT1, 
  10 ] = [wx.NewId() for _init_ctrls in range(5)]
  11 
  12 class Frame1(wx.Frame):
  13     def _init_coll_bsPanel_Items(self, parent):
  14         # generated method, don't edit
  15 
  16         parent.AddWindow(self.staticText1, 0, border=10,
  17               flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL | wx.ALL | wx.EXPAND)
  18         parent.AddSizer(self.fgsButtons, 1, border=2, flag=wx.ALL | wx.EXPAND)
  19 
  20     def _init_coll_fgsButtons_Items(self, parent):
  21         # generated method, don't edit
  22 
  23         parent.AddWindow(self.button1, 1, border=2, flag=wx.ALL | wx.EXPAND)
  24         parent.AddWindow(self.button2, 1, border=2, flag=wx.ALL | wx.EXPAND)
  25 
  26     def _init_coll_bsFrame_Items(self, parent):
  27         # generated method, don't edit
  28 
  29         parent.AddWindow(self.panel1, 1, border=2,
  30               flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL)
  31 
  32     def _init_coll_fgsButtons_Growables(self, parent):
  33         # generated method, don't edit
  34 
  35         parent.AddGrowableCol(0)
  36         parent.AddGrowableCol(1)
  37 
  38     def _init_sizers(self):
  39         # generated method, don't edit
  40         self.bsPanel = wx.BoxSizer(orient=wx.VERTICAL)
  41 
  42         self.bsFrame = wx.BoxSizer(orient=wx.VERTICAL)
  43 
  44         self.fgsButtons = wx.FlexGridSizer(cols=2, hgap=0, rows=0, vgap=0)
  45 
  46         self._init_coll_bsPanel_Items(self.bsPanel)
  47         self._init_coll_bsFrame_Items(self.bsFrame)
  48         self._init_coll_fgsButtons_Items(self.fgsButtons)
  49         self._init_coll_fgsButtons_Growables(self.fgsButtons)
  50 
  51         self.SetSizer(self.bsFrame)
  52         self.panel1.SetSizer(self.bsPanel)
  53 
  54     def _init_ctrls(self, prnt):
  55         # generated method, don't edit
  56         wx.Frame.__init__(self, id=wxID_FRAME1, name='', parent=prnt,
  57               pos=wx.Point(642, 279), size=wx.Size(236, 106),
  58               style=wx.DEFAULT_FRAME_STYLE, title='Frame1')
  59         self.SetClientSize(wx.Size(220, 70))
  60 
  61         self.panel1 = wx.Panel(id=wxID_FRAME1PANEL1, name='panel1', parent=self,
  62               pos=wx.Point(2, 2), size=wx.Size(216, 66),
  63               style=wx.TAB_TRAVERSAL)
  64 
  65         self.staticText1 = wx.StaticText(id=wxID_FRAME1STATICTEXT1,
  66               label=u'Hello world!', name='staticText1', parent=self.panel1,
  67               pos=wx.Point(10, 10), size=wx.Size(196, 13),
  68               style=wx.ALIGN_CENTRE)
  69 
  70         self.button1 = wx.Button(id=wxID_FRAME1BUTTON1, label='button1',
  71               name='button1', parent=self.panel1, pos=wx.Point(4, 37),
  72               size=wx.Size(100, 23), style=0)
  73 
  74         self.button2 = wx.Button(id=wxID_FRAME1BUTTON2, label='button2',
  75               name='button2', parent=self.panel1, pos=wx.Point(116, 37),
  76               size=wx.Size(100, 23), style=0)
  77 
  78         self._init_sizers()
  79 
  80     def __init__(self, parent):
  81         self._init_ctrls(parent)
  82         
  83 
  84 if __name__ == '__main__':
  85     app = wx.PySimpleApp()
  86     frame = create(None)
  87     frame.Show()
  88 
  89     app.MainLoop()

Other wiki pages to check

Comments

Please feel free to provide any feedback on this page either here, on the wxPython-user list or to werner.bruhin at free.fr.

cx_freeze (last edited 2009-07-24 08:08:16 by ABordeaux-156-1-12-192)