Hi, I got an private message from Osirus requesting that I share my py2exe code. I figure if it’s useful to one person, it may be useful to others.
I am writing a whole set of utilities based off of panda so I wrote a generic py2exe setup script that lets me easily retarget the python code that gets packaged.
The code is split up into two files build.py and pandasetup.py. build.py collects commandline arguments and calls setup. pandasetup.py just manages all of the directories and paths required to build panda into the final distibutable.
You should be able to make an exe w/this code using the following example commandline:
ppython -OO build.py -f mytestfile.py -r src
NOTE: in this example, your code would be in a directory named “src” and there would be a file in that directory called “mytestfile.py” that you wanted to turn into an .exe
However, I never run the code this way myself. Instead I made a target for apache ant that lets me run py2exe w/through these scripts during my build process. I included this code as well.
#Listing for build.py
import os
import glob
from pandasetup import *
#import distutils
from distutils.core import setup
from optparse import OptionParser
import sys
from string import *
import py2exe
parser = OptionParser()
parser.add_option("-p",
"--pandapath",
dest="pandapath",
default = "C:\\Panda3D-1.3.2",
help="Path to Panda")
parser.add_option("-r",
"--rootpath",
dest="rootpath",
default = "src",
help="Project Root")
parser.add_option("-f",
"--file",
dest="buildfile",
default = "test.py",
help="file to compile FILE", metavar="FILE")
parser.add_option("-d",
"--dist",
dest="distpath",
default = "dist",
help="Directory Output DIR",metavar="DIR")
parser.add_option("-l",
"--library",
dest="libfile",
default = "library.zip",
help="Zipfile libraryname")
parser.add_option("-w",
"--windowed",
dest="windowed",
default = False,
help="Run in windows mode")
parser.add_option("-i",
"--icon",
dest="icon_path",
default = "icon.ico",
help="Icon path")
(cmdopts, args) = parser.parse_args()
print "argv: "+str(sys.argv)
sys.argv=[sys.argv[0],'py2exe']
print "Current Working Dir: "+str(os.getcwd())
def createSetupCommandLine(pandapath,
rootpath,
buildfile,
distpath,
libfile,
iconpath,
isWindowed):
args ={}
if(isWindowed):
args['windows']=[{"script":os.path.join(rootpath,buildfile),"icon_resources":[(1,iconpath)]}]
else:
args['console']=[{"script":os.path.join(rootpath,buildfile),"icon_resources":[(1,iconpath)]}]
args['zipfile'] = libfile
py2exeOpts= {}
py2exeOpts['unbuffered']=True
py2exeOpts['optimize']=2
py2exeOpts['dist_dir']=distpath
args['options'] = {'py2exe':py2exeOpts}
args['packages'] = getPackages()
args['package_dir'] = getPackageDirs(pandapath,rootpath)
args['data_files'] = getDataFiles(pandapath)
return args
setupArgs =createSetupCommandLine(strip(cmdopts.pandapath),
os.path.join(os.getcwd(),strip(cmdopts.rootpath)),
strip(cmdopts.buildfile),
os.path.join(os.getcwd(),strip(cmdopts.distpath)),
strip(cmdopts.libfile),
cmdopts.icon_path,
cmdopts.windowed)
setup(**setupArgs)
#Listing for pandasetup.py
import os
import glob
def getPackages():
return [ '',
'direct',
'direct.directbase',
'direct.showbase',
'direct.interval',
'direct.actor',
'direct.gui',
'direct.task',
'direct.controls',
'direct.directnotify',
'direct.directtools',
'direct.directutil',
'direct.fsm',
'direct.cluster',
'direct.particles',
'direct.tkpanels',
'direct.tkwidgets',
'direct.directdevices',
'direct.distributed',
'pandac',
]
def getPackageDirs(pandapath,srcdir):
return { '':srcdir,
'direct' : os.path.join(pandapath, 'direct'),
'direct.directbase' : os.path.join(pandapath, 'direct/directbase'),
'direct.showbase' : os.path.join(pandapath, 'direct/showbase'),
'direct.interval' : os.path.join(pandapath, 'direct/interval'),
'direct.actor' : os.path.join(pandapath, 'direct/actor'),
'direct.gui' : os.path.join(pandapath, 'direct/gui'),
'direct.task' : os.path.join(pandapath, 'direct/task'),
'direct.controls' : os.path.join(pandapath, 'direct/controls'),
'direct.directnotify' : os.path.join(pandapath, 'direct/directnotify'),
'direct.directtools' : os.path.join(pandapath, 'direct/directtools'),
'direct.directutil' : os.path.join(pandapath, 'direct/directutil'),
'direct.fsm' : os.path.join(pandapath, 'direct/fsm'),
'direct.cluster' : os.path.join(pandapath, 'direct/cluster'),
'direct.particles' : os.path.join(pandapath, 'direct/particles'),
'direct.tkpanels' : os.path.join(pandapath, 'direct/tkpanels'),
'direct.tkwidgets' : os.path.join(pandapath, 'direct/tkwidgets'),
'direct.directdevices' : os.path.join(pandapath, 'direct/directdevices'),
'direct.distributed' : os.path.join(pandapath, 'direct/distributed'),
'pandac' : os.path.join(pandapath, 'pandac'),
}
def getDataFiles(pandapath):
return [ ('etc', [os.path.join(pandapath, 'etc/Config.prc')]),
# make sure all dlls are copied from Panda3D
('.', glob.glob(os.path.join(pandapath, 'bin/*.dll'))),
]
<!--ANT Py2exe code for panda-->
<project>
<property name="panda.dir" value="C:\Panda3D-1.3.2"/>
<property name="panda.bin.dir" value="${panda.dir}\bin"/>
<property name="panda.python.dir" value="${panda.dir}\python"/>
<property name="ppython.exe" value="${panda.python.dir}\ppython.exe"/>
<property name="py2exe.tools.dir" location="tools\py2exe"/>
<property name="py2exeHelper" value="${py2exe.tools.dir}\build.py"/>
<target name="py2exe">
<echo message="pyfile=${pyfile}"/>
<echo message="Python : ${ppython.exe}"/>
<echo message="Panda Dir: ${panda.dir}"/>
<echo message="Src Dir : ${src.dir}"/>
<echo message="Target File : ${pyfile}.py"/>
<echo message="Target Dir : ${target.dir}\${pyfile}"/>
<echo message="Library File : ${pyfile}.zip"/>
<exec executable="${ppython.exe}" failonerror="yes">
<arg value="-OO"/>
<arg value="${py2exeHelper}"/>
<arg value="-p ${panda.dir}"/>
<arg value="-r ${src.dir}"/>
<arg value="-f ${pyfile}.py"/>
<arg value="-d ${target.dir}\${pyfile}"/>
<arg value="-l ${pyfile}.zip"/>
<redirector output="${log.dir}/${pyfile}/${pyfile}.out.txt"
error="${log.dir}/${pyfile}/${pyfile}.err.txt">
</redirector>
</exec>
</target>
</project>