In October 2010, I published a small tutorial on how to build a .exe Windows executable for ETS (Enthought Tool Suite) 3.5.0 -based applications.
Today, I present the edited version of the setup script, to match the new Enthought Namespace !!
Goal:
Pack an ETS-based application in a executable .exe file for windows
Keys to remember:
- To get things to work, I had to manually import all packages used, surely the Wx backend.
- It’s not possible, currently, to bundle and to compress. [if you find out ‘how-to’, please let me know !]
- I add the /images folders manually using the data_files variable.
My Configuration:
- Windows 7 x64
- Python 2.7.1 (running 32bits, I think)
- numpy 1.5.1
- scipy 0.9.0
- py2exe 0.6.10dev
- ETS 4.0 from GitHub
So, here is a typical example :
from enthought.traits.api import * class Person(HasTraits): name = Str age = CInt weight = CFloat if __name__ == "__main__": joe = Person() joe.configure_traits() print joe.name, joe.age, joe.weight
You’ll see below, the ETS from GitHub is downloaded in “c:\ETSgit”
The setup.py script looks like :
from distutils.core import setup import py2exe import os import glob includes = [] includes.append('numpy') includes.append('numpy.core') includes.append('configobj') includes.append('reportlab') includes.append('reportlab.pdfbase') includes.append('reportlab.pdfbase.*') includes.append('scipy') includes.append('xml') includes.append('xml.etree') includes.append('xml.etree.*') includes.append('wx') includes.append('wx.*') includes.append('traits') includes.append('traitsui') includes.append('traitsui.editors') includes.append('traitsui.editors.*') includes.append('traitsui.extras') includes.append('traitsui.extras.*') includes.append('traitsui.wx') includes.append('traitsui.wx.*') includes.append('kiva') includes.append('pyface') includes.append('pyface.*') includes.append('pyface.wx') includes.append('pyface.ui.wx') includes.append('pyface.ui.wx.init') includes.append('pyface.ui.wx.*') includes.append('pyface.ui.wx.grid.*') includes.append('pyface.ui.wx.action.*') includes.append('pyface.ui.wx.timer.*') includes.append('pyface.ui.wx.wizard.*') includes.append('pyface.ui.wx.workbench.*') includes.append('enable') includes.append('enable.drawing') includes.append('enable.tools') includes.append('enable.wx') includes.append('enable.wx.*') includes.append('enable.savage') includes.append('enable.savage.*') includes.append('enable.savage.svg') includes.append('enable.savage.svg.*') includes.append('enable.savage.svg.backends') includes.append('enable.savage.svg.backends.wx') includes.append('enable.savage.svg.backends.wx.*') includes.append('enable.savage.svg.css') includes.append('enable.savage.compliance') includes.append('enable.savage.trait_defs') includes.append('enable.savage.trait_defs.*') includes.append('enable.savage.trait_defs.ui') includes.append('enable.savage.trait_defs.ui.*') includes.append('enable.savage.trait_defs.ui.wx') includes.append('enable.savage.trait_defs.ui.wx.*') packages = [] data_folders = [] # Traited apps: ETS_folder = r'C:\ETSgit' data_folders.append( ( os.path.join(ETS_folder,r'enable\enable\images') , r'enable/images') ) data_folders.append( ( os.path.join(ETS_folder,r'pyface\pyface\images') , r'pyface\images') ) data_folders.append( ( os.path.join(ETS_folder,r'pyface\pyface\ui\wx\images') , r'pyface\ui\wx\images') ) data_folders.append( ( os.path.join(ETS_folder,r'pyface\pyface\ui\wx\grid\images') , r'pyface\ui\wx\grid\images') ) data_folders.append( ( os.path.join(ETS_folder,r'traitsui\traitsui\wx\images') , r'traitsui\wx\images') ) data_folders.append( ( os.path.join(ETS_folder,r'traitsui\traitsui\image\library') , r'traitsui\image\library') ) data_folders.append( ( os.path.join(ETS_folder,r'enable\enable\savage\trait_defs\ui\wx\data') , r'enable\savage\trait_defs\ui\wx\data') ) # Matplotlib import matplotlib as mpl data_files = mpl.get_py2exe_datafiles() # Parsing folders and building the data_files table for folder, relative_path in data_folders: for file in os.listdir(folder): f1 = os.path.join(folder,file) if os.path.isfile(f1): # skip directories f2 = relative_path, [f1] data_files.append(f2) data_files.append((r'enable',[os.path.join(ETS_folder,r'enable\enable\images.zip')])) setup(windows=['example.py'], author="Geophysique.be", version = "1.1", description = "Geophysique.be ETS4.0/Py2exe example", name = "DP - ROB Data Processing Tool", options = {"py2exe": { "optimize": 0, "packages": packages, "includes": includes, "dist_dir": 'dist', "bundle_files":2, "xref": False, "skip_archive": True, "ascii": False, "custom_boot_script": '', "compressed":False, },}, data_files=data_files)
then, to launch the packing, just do:
$ python setup.py py2exe
The build and packing process takes some time, but it works. The /dist directory contains a lot of libraries (~73 MB), there must be a way to cut down the imports, but I have to admit, now that I have a successful build, I really don’t care if it’s 110 MB or 80 MB ! I left the lines to include the matplotlib data files, although they are not needed for this example.
to launch the script, just hit “example.exe” in the /dist folder. Note, I set the “console” value to “example.py”, because I wanted to have a python console running behind my GUI. If you replace “console” by “windows”, double-clicking “example.exe” will just load your GUI.
FYI, I successfully packed our new seismic waveform data processing application using the script above !!
Cheeeeeeeeeeeeeeeeeeeers !
Thom
hi,Thomas
I have tried your emaxple, I installed pythonxy instead of ETS4.0, So the ETS_folder = r’C:\Python27\Lib\site-packages’, In this folder,It have ‘enable’,’pyface’,’traitsui’ subfolders. I have modified the setup.py. However, When I ‘python setup.py py2exe’,And run the example.exe, The error are as follows:
Traceback (most recent call last):
File “Traits_app_py2exe.py”, line 1, in
ImportError: No module named enthought.traits.api
Traceback (most recent call last):
File “Traits_app_py2exe.py”, line 1, in
ImportError: No module named enthought.traits.api
Could you help me how to deal with it??
My example is wrong in that, now, the enthought namespace has disappeared, you have to import
traits.api
andtraitsui.api
without theenthought
prefix !Obviously, before py2exe a code, you should be sure it runs on your normal python install… Does it ? Let me know how it goes !
Hi,Thomas
your example of traitsui demo can run well on my normal python install.
and follow your advice,I change ” from enthought.traits.api import * ” to ” from traits.api import * ”
also works!
But after I py2exe the demo ,the errors has changed ,Here it is:
Traceback (most recent call last):
File “Traits_app_py2exe.py”, line 10, in
File “traits\has_traits.pyc”, line 2563, in configure_traits
File “traitsui\wx\toolkit.pyc”, line 219, in view_application
File “traitsui\wx\view_application.pyc”, line 80, in view_application
File “traitsui\wx\view_application.pyc”, line 123, in __init__
File “wx\_core.pyc”, line 8081, in __init__
File “wx\_core.pyc”, line 7981, in __init__
File “wx\_core.pyc”, line 7555, in _BootstrapApp
e”
File “traitsui\wx\view_application.pyc”, line 140, in OnInit
File “traitsui\view.pyc”, line 433, in ui
File “traitsui\ui.pyc”, line 218, in ui
File “traitsui\wx\toolkit.pyc”, line 140, in ui_live
File “traitsui\wx\ui_live.pyc”, line 68, in ui_live
File “traitsui\wx\ui_live.pyc”, line 99, in ui_dialog
File “traitsui\wx\ui_live.pyc”, line 194, in init
File “traitsui\wx\ui_base.pyc”, line 142, in set_icon
File “pyface\ui\wx\image_resource.pyc”, line 67, in create_icon
File “pyface\i_image_resource.pyc”, line 126, in _get_image_not_found_image
File “pyface\i_image_resource.pyc”, line 103, in create_image
File “pyface\i_image_resource.pyc”, line 129, in _get_image_not_found_image
ValueError: cannot locate the file for ‘image_not_found’
I don’t know why?
It’s most probably an issue of data (image, static file) missing in the pyface module. In the setup script, there are a few lines about those images, to list them and “move” them to the right folder. I’ll try to rerun this example with the latest git clone and I’ll update it asap!