⇤ ← Revision 1 as of 2009-05-16 11:32:25
Size: 5575
Comment:
|
Size: 11371
Comment:
|
Deletions are marked like this. | Additions are marked like this. |
Line 10: | Line 10: |
Line 11: | Line 12: |
Line 12: | Line 14: |
Line 16: | Line 19: |
A tiny sample wxPython "Hello world" application will be used to demonstrate the process. I created the tiny application using [[https://sourceforge.net/projects/boa-constructor/|Boa Constructor]] but you could use any other IDE you use for your wxPython development. The creation of the setup.py file I did using Gui2Exe, but again one could create this by hand. | A tiny sample wxPython "Hello world" application will be used to demonstrate the process. I created the tiny application using [[https://sourceforge.net/projects/boa-constructor/|Boa Constructor]] but you could use any other IDE you use for your wxPython development. The creation of the setup.py file I did using [[http://code.google.com/p/gui2exe/|Gui2Exe]], but again one could create this by hand. |
Line 21: | Line 24: |
* you will need the MS C run time dll (msvcr71.dll) | * you will need the MS C run time dll 'msvcr71.dll', included with Python * the dll 'gdiplus.dll' might also be needed depending on what wxPython widgets you use |
Line 24: | Line 29: |
* you will need the MS C run time dll's (msvcr90.dll, msvcp90.dll, msvcm90.dll) * you will a Microsoft.VC90.CRT.manifest file |
* you will need the MS C run time dll's (msvcr90.dll, msvcp90.dll, msvcm90.dll), included with Python (see the SxS folder under Windows) * you will need a copy of the Microsoft.VC90.CRT.manifest file * the dll 'gdiplus.dll' might also be needed depending on what wxPython widgets you use == The setup.py == Save the following code in your working folder as a file called 'setup.py'. {{{ #!python # ======================================================# # File automagically generated by GUI2Exe version 0.3 # Andrea Gavana, 01 April 2007 # ======================================================# # Let's start with some default (for me) imports... from distutils.core import setup import py2exe import glob import os import zlib import shutil # Remove the build folder shutil.rmtree("build", ignore_errors=True) print 'is this shown' class Target(object): """ A simple class that holds information on our executable file. """ def __init__(self, **kw): """ Default class constructor. Update as you need. """ self.__dict__.update(kw) # Ok, let's explain why I am doing that. # Often, data_files, excludes and dll_excludes (but also resources) # can be very long list of things, and this will clutter too much # the setup call at the end of this file. So, I put all the big lists # here and I wrap them using the textwrap module. data_files = [] includes = [] excludes = ['_gtkagg', '_tkagg', 'bsddb', 'curses', 'email', 'pywin.debugger', 'pywin.debugger.dbgcon', 'pywin.dialogs', 'tcl', 'Tkconstants', 'Tkinter'] packages = [] dll_excludes = ['libgdk-win32-2.0-0.dll', 'libgobject-2.0-0.dll', 'tcl84.dll', 'tk84.dll'] icon_resources = [] bitmap_resources = [] other_resources = [] # This is a place where the user custom code may go. You can do almost # whatever you want, even modify the data_files, includes and friends # here as long as they have the same variable name that the setup call # below is expecting. baseFolder, progFolder = os.path.split(os.getcwd()) # # The following will copy the MSVC run time dll's # (msvcm90.dll, msvcp90.dll and msvcr90.dll) and # the Microsoft.VC90.CRT.manifest which I keep in the # "Py26MSdlls" folder to the dist folder # # depending on wx widgets you use, you might need to add # gdiplus.dll to the above collection py26MSdll = glob.glob(r"c:\dev\Py26MSdlls\*.*") data_files += [("", py26MSdll), ] # Ok, now we are going to build our target class. # I chose this building strategy as it works perfectly for me :-D GUI2Exe_Target_1 = Target( # what to build script = "simplewx.py", icon_resources = icon_resources, bitmap_resources = bitmap_resources, other_resources = other_resources, dest_base = "simplewx", version = "0.1", company_name = "No Company", copyright = "No Copyrights", name = "Py2Exe Sample File" ) # That's serious now: we have all (or almost all) the options py2exe # supports. I put them all even if some of them are usually defaulted # and not used. Some of them I didn't even know about. setup( data_files = data_files, options = {"py2exe": {"compressed": 2, "optimize": 2, "includes": includes, "excludes": excludes, "packages": packages, "dll_excludes": dll_excludes, "bundle_files": 3, "dist_dir": "dist", "xref": False, "skip_archive": False, "ascii": False, "custom_boot_script": '', } }, zipfile = r'lib/library.zip', console = [], windows = [GUI2Exe_Target_1] ) # And we are done. That's a setup script :-D # Run setup standalone... if __name__ == "__main__": print 'just running setup' setup() print 'setup done' print 'clean up' # This is a place where any post-compile code may go. # You can add as much code as you want, which can be used, for example, # to clean up your folders or to do some particular post-compilation # actions. # for some reason some files remain sometimes in dist, but they # are already present in dist/lib, so lets remove them # cwdFolder = os.getcwd() libFile = os.path.join(cwdFolder, 'dist\\library.zip') if os.path.exists(libFile): print 'deleting duplicate files' os.remove(libFile) os.remove(os.path.join(cwdFolder, 'dist\\bz2.pyd')) os.remove(os.path.join(cwdFolder, 'dist\\select.pyd')) os.remove(os.path.join(cwdFolder, 'dist\\unicodedata.pyd')) }}} == The MS manifest == Following is the content of the Microsoft manifest file, note that the content of "version" and "publicKeyToken" are specific to the version of the dll files. Installing Python 2.6 on Windows 7rc1 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. {{{ #!xml <?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> }}} |
Line 29: | Line 209: |
Create a folder and save the following code as a file called 'simplewx.py'. | Save the following code in your working folder as a file called 'simplewx.py'. |
Line 98: | Line 278: |
Line 101: | Line 280: |
Create a folder and save the following code as a file called 'simplewx.py'. | Save the following code in your working folder as a file called 'simplewx.py'. |
Line 173: | Line 352: |
This is the place that you can add your plans for the future of this page, tell people how to contact you, or leave feedback for the author of the page. | Please feel free to provide any feedback on this page either here, on the wxPython-user list or to werner.bruhin at free.fr. |
Introduction
The following will explain how to freeze a Python/wxPython application using the py2exe tool.
What Objects are Involved
You will need a working development environment including
* Python
* wxPython
* py2exe
Process Overview
A tiny 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. The creation of the setup.py file I did using Gui2Exe, but again one could create this by hand.
Special Concerns
Python 2.5x
- you will need the MS C run time dll 'msvcr71.dll', included with Python
- the dll 'gdiplus.dll' might also be needed depending on what wxPython widgets you use
Python 2.6x
- you will need the MS C run time dll's (msvcr90.dll, msvcp90.dll, msvcm90.dll), included with Python (see the SxS folder under Windows)
- you will need a copy of the Microsoft.VC90.CRT.manifest file
- the dll 'gdiplus.dll' might also be needed depending on what wxPython widgets you use
The setup.py
Save the following code in your working folder as a file called 'setup.py'.
1 # ======================================================#
2 # File automagically generated by GUI2Exe version 0.3
3 # Andrea Gavana, 01 April 2007
4 # ======================================================#
5
6 # Let's start with some default (for me) imports...
7
8 from distutils.core import setup
9 import py2exe
10 import glob
11 import os
12 import zlib
13 import shutil
14
15 # Remove the build folder
16 shutil.rmtree("build", ignore_errors=True)
17
18 print 'is this shown'
19
20 class Target(object):
21 """ A simple class that holds information on our executable file. """
22 def __init__(self, **kw):
23 """ Default class constructor. Update as you need. """
24 self.__dict__.update(kw)
25
26
27 # Ok, let's explain why I am doing that.
28 # Often, data_files, excludes and dll_excludes (but also resources)
29 # can be very long list of things, and this will clutter too much
30 # the setup call at the end of this file. So, I put all the big lists
31 # here and I wrap them using the textwrap module.
32
33 data_files = []
34
35 includes = []
36 excludes = ['_gtkagg', '_tkagg', 'bsddb', 'curses', 'email', 'pywin.debugger',
37 'pywin.debugger.dbgcon', 'pywin.dialogs', 'tcl',
38 'Tkconstants', 'Tkinter']
39 packages = []
40 dll_excludes = ['libgdk-win32-2.0-0.dll', 'libgobject-2.0-0.dll', 'tcl84.dll',
41 'tk84.dll']
42 icon_resources = []
43 bitmap_resources = []
44 other_resources = []
45
46
47 # This is a place where the user custom code may go. You can do almost
48 # whatever you want, even modify the data_files, includes and friends
49 # here as long as they have the same variable name that the setup call
50 # below is expecting.
51
52 baseFolder, progFolder = os.path.split(os.getcwd())
53
54 #
55 # The following will copy the MSVC run time dll's
56 # (msvcm90.dll, msvcp90.dll and msvcr90.dll) and
57 # the Microsoft.VC90.CRT.manifest which I keep in the
58 # "Py26MSdlls" folder to the dist folder
59 #
60 # depending on wx widgets you use, you might need to add
61 # gdiplus.dll to the above collection
62
63 py26MSdll = glob.glob(r"c:\dev\Py26MSdlls\*.*")
64
65 data_files += [("", py26MSdll),
66 ]
67
68
69 # Ok, now we are going to build our target class.
70 # I chose this building strategy as it works perfectly for me :-D
71
72
73 GUI2Exe_Target_1 = Target(
74 # what to build
75 script = "simplewx.py",
76 icon_resources = icon_resources,
77 bitmap_resources = bitmap_resources,
78 other_resources = other_resources,
79 dest_base = "simplewx",
80 version = "0.1",
81 company_name = "No Company",
82 copyright = "No Copyrights",
83 name = "Py2Exe Sample File"
84 )
85
86
87
88 # That's serious now: we have all (or almost all) the options py2exe
89 # supports. I put them all even if some of them are usually defaulted
90 # and not used. Some of them I didn't even know about.
91
92 setup(
93
94 data_files = data_files,
95
96 options = {"py2exe": {"compressed": 2,
97 "optimize": 2,
98 "includes": includes,
99 "excludes": excludes,
100 "packages": packages,
101 "dll_excludes": dll_excludes,
102 "bundle_files": 3,
103 "dist_dir": "dist",
104 "xref": False,
105 "skip_archive": False,
106 "ascii": False,
107 "custom_boot_script": '',
108 }
109 },
110
111 zipfile = r'lib/library.zip',
112 console = [],
113 windows = [GUI2Exe_Target_1]
114 )
115
116
117 # And we are done. That's a setup script :-D
118
119 # Run setup standalone...
120 if __name__ == "__main__":
121 print 'just running setup'
122 setup()
123 print 'setup done'
124
125 print 'clean up'
126
127 # This is a place where any post-compile code may go.
128 # You can add as much code as you want, which can be used, for example,
129 # to clean up your folders or to do some particular post-compilation
130 # actions.
131
132 # for some reason some files remain sometimes in dist, but they
133 # are already present in dist/lib, so lets remove them
134 #
135
136 cwdFolder = os.getcwd()
137 libFile = os.path.join(cwdFolder, 'dist\\library.zip')
138 if os.path.exists(libFile):
139 print 'deleting duplicate files'
140 os.remove(libFile)
141 os.remove(os.path.join(cwdFolder, 'dist\\bz2.pyd'))
142 os.remove(os.path.join(cwdFolder, 'dist\\select.pyd'))
143 os.remove(os.path.join(cwdFolder, 'dist\\unicodedata.pyd'))
The MS manifest
Following is the content of the Microsoft manifest file, note that the content of "version" and "publicKeyToken" are specific to the version of the dll files. Installing Python 2.6 on Windows 7rc1 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.
<?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_FRAME1PANEL1, wxID_FRAME1STATICTEXT1,
9 ] = [wx.NewId() for _init_ctrls in range(3)]
10
11 class Frame1(wx.Frame):
12 def _init_coll_bsPanel_Items(self, parent):
13 # generated method, don't edit
14
15 parent.AddWindow(self.staticText1, 0, border=10,
16 flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL | wx.ALL | wx.EXPAND)
17
18 def _init_coll_bsFrame_Items(self, parent):
19 # generated method, don't edit
20
21 parent.AddWindow(self.panel1, 1, border=2,
22 flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL)
23
24 def _init_sizers(self):
25 # generated method, don't edit
26 self.bsPanel = wx.BoxSizer(orient=wx.VERTICAL)
27
28 self.bsFrame = wx.BoxSizer(orient=wx.VERTICAL)
29
30 self._init_coll_bsPanel_Items(self.bsPanel)
31 self._init_coll_bsFrame_Items(self.bsFrame)
32
33 self.panel1.SetSizer(self.bsPanel)
34 self.SetSizer(self.bsFrame)
35
36 def _init_ctrls(self, prnt):
37 # generated method, don't edit
38 wx.Frame.__init__(self, id=wxID_FRAME1, name='', parent=prnt,
39 pos=wx.Point(642, 279), size=wx.Size(124, 86),
40 style=wx.DEFAULT_FRAME_STYLE, title='Frame1')
41 self.SetClientSize(wx.Size(108, 50))
42
43 self.panel1 = wx.Panel(id=wxID_FRAME1PANEL1, name='panel1', parent=self,
44 pos=wx.Point(2, 2), size=wx.Size(104, 46),
45 style=wx.TAB_TRAVERSAL)
46
47 self.staticText1 = wx.StaticText(id=wxID_FRAME1STATICTEXT1,
48 label=u'Hello world!', name='staticText1', parent=self.panel1,
49 pos=wx.Point(10, 10), size=wx.Size(84, 13),
50 style=wx.ALIGN_CENTRE)
51
52 self._init_sizers()
53
54 def __init__(self, parent):
55 self._init_ctrls(parent)
56
57
58 if __name__ == '__main__':
59 app = wx.PySimpleApp()
60 frame = create(None)
61 frame.Show()
62
63 app.MainLoop()
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_FRAME1PANEL1, wxID_FRAME1STATICTEXT1,
9 ] = [wx.NewId() for _init_ctrls in range(3)]
10
11 class Frame1(wx.Frame):
12 def _init_coll_bsPanel_Items(self, parent):
13 # generated method, don't edit
14
15 parent.AddWindow(self.staticText1, 0, border=10,
16 flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL | wx.ALL | wx.EXPAND)
17
18 def _init_coll_bsFrame_Items(self, parent):
19 # generated method, don't edit
20
21 parent.AddWindow(self.panel1, 1, border=2,
22 flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL)
23
24 def _init_sizers(self):
25 # generated method, don't edit
26 self.bsPanel = wx.BoxSizer(orient=wx.VERTICAL)
27
28 self.bsFrame = wx.BoxSizer(orient=wx.VERTICAL)
29
30 self._init_coll_bsPanel_Items(self.bsPanel)
31 self._init_coll_bsFrame_Items(self.bsFrame)
32
33 self.panel1.SetSizer(self.bsPanel)
34 self.SetSizer(self.bsFrame)
35
36 def _init_ctrls(self, prnt):
37 # generated method, don't edit
38 wx.Frame.__init__(self, id=wxID_FRAME1, name='', parent=prnt,
39 pos=wx.Point(642, 279), size=wx.Size(124, 86),
40 style=wx.DEFAULT_FRAME_STYLE, title='Frame1')
41 self.SetClientSize(wx.Size(108, 50))
42
43 self.panel1 = wx.Panel(id=wxID_FRAME1PANEL1, name='panel1', parent=self,
44 pos=wx.Point(2, 2), size=wx.Size(104, 46),
45 style=wx.TAB_TRAVERSAL)
46
47 self.staticText1 = wx.StaticText(id=wxID_FRAME1STATICTEXT1,
48 label=u'Hello world!', name='staticText1', parent=self.panel1,
49 pos=wx.Point(10, 10), size=wx.Size(84, 13),
50 style=wx.ALIGN_CENTRE)
51
52 self._init_sizers()
53
54 def __init__(self, parent):
55 self._init_ctrls(parent)
56
57
58 if __name__ == '__main__':
59 app = wx.PySimpleApp()
60 frame = create(None)
61 frame.Show()
62
63 app.MainLoop()
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.