using py2exe , Panda3d and Python 2.4

I can create and run the .exe no matter where my .py is, inside \python or outside.

Try these :

  1. create this .py in your \dist :
import os, imp
imp.load_dynamic('libpandaexpress', os.path.join(os.getcwd(),'libpandaexpress.dll'))

There shouldn’t be any error if you can run panda normally.

  1. open your \pandac\extension_native_helpers.py, insert these at the end of the 1st if block (line 19) :
    path=os.environ["PATH"]
    print '#####\nmy libpandaexpress PATH :\n%s\n#####\n' %path[:path.find(';')]

and run py2exe again (use console, not windows).
Run the .exe and watch your console, and post the path.

Now I did following:

What to do now?

@ynjh_jo: I only get this problem with the unloadable dll if I am running the exe on a computer without panda installed…some computers it errors and some it doesn’t…They are all running xp service pack 2, and doesn’t seem to make sense to me.

I guess I know what’s going on. Start your reading here :
forums.microsoft.com/MSDN/ShowPo … 7&SiteID=1

shortly : assuming your target comp’s processor is x86 family, deploy yourPanda3D\bin\vcredist_x86-sp1.exe to your target computer and install it first. Perhaps it’d be better distributing it along with the individual C/C++ runtime .dlls (msvcm80.dll, msvcp80.dll, msvcr80.dll, Microsoft.VC80.CRT.manifest)

Read for more :

:smiley:
Oh my God!!!. It works.
Thanks a lot. I can’t believe it.Awesome!!!

I’ve been pulling my hair out for this thing for last so many days…rather weeks.
I am really grateful to you.

good to hear that !

You should thank google, too. :smiley:

Can I ask one more question please…

Suppose we want to convert the Roaming Ralph sample py file to EXE
What should be the setup.py like?

Actually my sample file that I am trying to convert to exe, contains same (environment/actor) egg files as roaming ralph example does.
While py2exe is running following error comes:

Following is my setup.py

from distutils.core import setup 
import py2exe 
import os,sys 
PANDA_DIR = 'E:\ALL\Panda3D-1.4.2/' 

setup( windows = [ {  'script' : 'E:\ALL\Panda3D-1.4.2\Tut-Roaming-Ralph.py', 
                     'icon_resources' : [ ( 1, 'E:\ALL\Panda3D-1.4.2\mySiteLogo.ico' ) ], 
                     } ], 
       #zipfile = None, 
       options = { 'py2exe': { 'optimize' : 2, 
                               'excludes' : [ 'Tkinter' ], 
                'dist_dir' : 'dist/'}, 
                 }, 
       data_files = [ ( 'etc', [ os.path.join(PANDA_DIR, 'etc/Config.prc'), ] ), 
		     ( 'models', [ os.path.join(PANDA_DIR, 'models/*.*'), ] ),

                      ], 
       packages = [ 
        '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', 
                   ], 
      package_dir = { 
        'direct' : os.path.join(PANDA_DIR, 'direct'), 
        'direct.directbase' : os.path.join(PANDA_DIR, 'direct/directbase'), 
        'direct.showbase' : os.path.join(PANDA_DIR, 'direct/showbase'), 
        'direct.interval' : os.path.join(PANDA_DIR, 'direct/interval'), 
        'direct.actor' : os.path.join(PANDA_DIR, 'direct/actor'), 
        'direct.gui' : os.path.join(PANDA_DIR, 'direct/gui'), 
        'direct.task' : os.path.join(PANDA_DIR, 'direct/task'), 
        'direct.control' : os.path.join(PANDA_DIR, 'direct/control'), 
        'direct.directnotify' : os.path.join(PANDA_DIR, 'direct/directnotify'), 
        'direct.directtools' : os.path.join(PANDA_DIR, 'direct/directtools'), 
        'direct.directutil' : os.path.join(PANDA_DIR, 'direct/directutil'), 
        'direct.fsm' : os.path.join(PANDA_DIR, 'direct/fsm'), 
        'direct.cluster' : os.path.join(PANDA_DIR, 'direct/cluster'), 
        'direct.particles' : os.path.join(PANDA_DIR, 'direct/particles'), 
        'direct.tkpanels' : os.path.join(PANDA_DIR, 'direct/tkpanels'), 
        'direct.tkwidgets' : os.path.join(PANDA_DIR, 'direct/tkwidgets'), 
        'direct.directdevices' : os.path.join(PANDA_DIR, 'direct/directdevices'), 
        'direct.distributed' : os.path.join(PANDA_DIR, 'direct/distributed'), 
        'pandac' : os.path.join(PANDA_DIR, 'pandac'), 
                    }, 
) 

I am just trying to include all models and models/maps to my structure as well.

[size=134]1[/size], py2exe doesn’t accept wildcards in any form. So os.path.join(PANDA_DIR, ‘models/.’) won’t include all files in \models. Py2exe wants individual filenames.
You should provide every existing files there (1st, you should import glob) :

    ( 'models', glob.glob(os.path.join(PANDA_DIR, 'models/*.*')) ), # P3D's \models
    ( 'models/maps', glob.glob(os.path.join(PANDA_DIR, 'models/maps/*.*')) ), # P3D's \models\maps
    ( 'models', glob.glob('models/*.*') ), # Ralph's \models

Currently I don’t know anyway in pure Python to list all files in a directory, recursively. Neither glob.glob nor os.listdir work recursively. The only way I know is using os.system, ie. using legacy DOS command “dir . /s /b /a-d > file”, then read that file in Python and sort & group the files based on the location. No problem, like this :

import os
# put this script in  your \Panda3D,
# and it will list all files in \models recursively
myPath = 'models'

cwd=os.getcwd()
myFullPath = os.path.join(cwd,myPath)
myPathLen = len(cwd)+1

fileslistName="fileslist"
os.system( 'dir %s\*.* /s /b /a-d > %s' %(myFullPath,fileslistName) )
fr=open(fileslistName,"r")
fileslist = [ f[myPathLen:-1] for f in fr.readlines() ]
fr.close()
os.remove(os.path.join(cwd,fileslistName))

dirNfiles = {}
for f in fileslist:
    dir=f[:f.rfind('\\')]
    if not dir in dirNfiles:
       dirNfiles[dir]=[f]
    else:
       dirNfiles[dir]+=[f]

k=dirNfiles.keys()
k.sort()
for d in k:
    print '\n### %s ###' %d
    print '\n'.join(dirNfiles[d])

output :
[size=59]### models ###
models\box.egg.pz
models\camera.egg.pz
models\cmr12.egg.pz
models\cmss12.egg.pz
models\cmtt12.egg.pz
models\environment.egg.pz
models\frowney.egg.pz
models\jack.egg.pz
models\panda-model.egg.pz
models\panda-walk.egg.pz
models\panda-walk4.egg.pz
models\panda.egg.pz
models\ripple.egg.pz
models\shuttle_controls.egg.pz
models\smiley.egg.pz
models\teapot.egg.pz
models\yup-axis.egg.pz
models\zup-axis.egg.pz

models\audio\sfx

models\audio\sfx\GUI_click.wav
models\audio\sfx\GUI_rollover.wav

models\gui

models\gui\dialog_box_gui.egg.pz

models\icons

models\icons\actor.gif
models\icons\blank.gif
models\icons\control.gif
models\icons\folder.gif
models\icons\grid.gif
models\icons\help.gif
models\icons\lights.gif
models\icons\minusnode.gif
models\icons\model.gif
models\icons\mopath.gif
models\icons\new.gif
models\icons\open.gif
models\icons\openfolder.gif
models\icons\particles.gif
models\icons\placer.gif
models\icons\plusnode.gif
models\icons\python.gif
models\icons\save.gif
models\icons\smoke.gif
models\icons\sphere2.gif
models\icons\tk.gif
models\icons\Thumbs.db

models\maps

models\maps\4map.rgb
models\maps\Dirlight.png
models\maps\Pointlight.png
models\maps\Spotlight.png
models\maps\cmr12.rgb
models\maps\cmss12.rgb
models\maps\cmtt12.rgb
models\maps\color-grid.rgb
models\maps\envir-bamboo.png
models\maps\envir-cylinder.png
models\maps\envir-ground.jpg
models\maps\envir-groundcover1.png
models\maps\envir-mountain1.png
models\maps\envir-mountain2.png
models\maps\envir-reeds.png
models\maps\envir-rock1.jpg
models\maps\envir-rock2.jpg
models\maps\envir-tree1.png
models\maps\envir-tree2.png
models\maps\envir-treetrunk.jpg
models\maps\general_panel.rgba
models\maps\grid.rgb
models\maps\lilsmiley.rgba
models\maps\noise.rgb
models\maps\panda-model.jpg
models\maps\panda_hat.rgb
models\maps\panda_head.rgb
models\maps\panda_torso.rgb
models\maps\panda_viser.rgb
models\maps\shuttle_controls_1.rgb
models\maps\smiley.rgb
models\maps\soft_iris.rgb
models\maps\Thumbs.db
models\maps\Copy of frowney.rgb
models\maps\frowney.rgb

models\misc

models\misc\Dirlight.egg.pz
models\misc\Pointlight.egg.pz
models\misc\Spotlight.egg.pz
models\misc\camera.egg.pz
models\misc\fade.egg.pz
models\misc\fade_sphere.egg.pz
models\misc\gridBack.egg.pz
models\misc\iris.egg.pz
models\misc\lilsmiley.egg.pz
models\misc\objectHandles.egg.pz
models\misc\rgbCube.egg.pz
models\misc\smiley.egg.pz
models\misc\sphere.egg.pz
models\misc\xyzAxis.egg.pz[/size]

[size=134]2[/size], I don’t know why your script & icon paths are both absolute. Are you running “python setup.py py2exe” not from E:\ALL\Panda3D-1.4.2 ? If you’re already there, you don’t need to use absolute path. Simply Tut-Roaming-Ralph.py and mySiteLogo.ico DO work.
Or, are you toooooo lazy to go there with command prompt ? Doesn’t matter, there is a shortcut.
To run py2exe in the location of your setup.py, you could add py2exe to Windows explorer’s context menu.
First, create a batch file (text file with .bat extension) somewhere safe from deletion due to uninstalling any program.
content :

python setup.py py2exe
pause

save as .bat file.

  1. open Folder Options (Control Panel>>FolderOptions, or Tool>>FolderOptions in Win explorer)
  2. bring up the File Types tab.
  3. select “Folder” type (be very careful, don’t mess up with “File Folder” type, it can ruin the actions priority, and you’d have to fix it only by editing the registry !) and click Advanced.
  4. create new action, you could name it “PY>2>EXE”, or anything you like, without quotes.
  5. click Browse, and select the batch file you just created as the application used to perform action.
  6. confirm everything.

note : “Folder” is the folders in the left panel of windows explorer, while the ones in the right panel are called “File Folder”.

So, now if you right-click the folder of your setup.py in the left panel, there will be “PY>2>EXE”, click it and py2exe will run normally. It’s just 2 clicks away ! :smiley:

Same steps applied if you want to open command prompt in arbitrary location, just change these 2 :
4. create new action, you could name it “PROMPT to here” without quotes.
5. click Browse, and select cmd.exe in \WINDOWS\system32 as the application used to perform action.

[size=134]3[/size], I don’t know why you like scratching your wound. Why didn’t you include the missing .dlls ?
I found that py2exe can’t detect the needed .dlls well. For app using audio and video, the .dlls (codec & sound lib) didn’t copied to \dist. I think it’d better to include all .dlls in \bin.

  P3DmissingDLLs=glob.glob(os.path.join(PANDA_DIR, 'bin/*.dll'))

It’d be better to include all .prc, since the “default-model-extension egg” is in Confauto.prc, which is not included. It would cause loadModel wants explicit .egg extension, which would crash P3D if you use implicit name, like in Ralph code.

os.walk will parse directories recursively. It returns a tuple containing a list of file names for each directory visited, and using os.path.join and you can create a single list of filenames pretty easily.

Even if I successfully give all paths in data_files, even then when i run the exe following error occurs:

I am just loading the environment file (in Roaming Ralph Example).
What could be the reason?

[size=150]WOW, DELICIOUS, ARKAEIN !![/size]
Thanks for your light.
I knew it, it must be there already.

Smriti, as I said, include all .prc files. Try to use console output, not windows, to see the complete traceback :

I’ve incorporated os.walk in my (once again) updated setup.py above.
I’m just fine with my setup.py

Thanks a million… to all.
:smiley:

My special thanks to:
ynjh_jo
enn0x
mindstormss

Without your effort it would have been impossible for a newbie, like me, to use py2exe.

Many thanks from this lurker too! This thread helped me solve my problem in about a tenth (or more!) of the time it would have taken me otherwise!

I am looking at using Panda for a commercial PC game, and getting end to end deployment working is a first step for that.