Pmw and Py2Exe Isses

Hi, I’m actually not asking a question, I’m posting a fix to an issue I ran into. I was using py2exe to package up a test app I wrote using panda and tkwidgets. I got a nasty error involving the Pmw module packaged w/panda that prevented the game from running as a .exe. The fix involves ‘Freezing’ Pmw using a script from the pmw maintainers and making a very small edit to TKGlobal.py in the panda 1.3.2 distribution. Below is a more detailed description of the steps I took.

This info relates to the following previous posts by myself and others on panda and py2Exe:

https://discourse.panda3d.org/viewtopic.php?t=1629&highlight=py2exe
https://discourse.panda3d.org/viewtopic.php?t=2091&highlight=py2exe
https://discourse.panda3d.org/viewtopic.php?t=901&highlight=py2exe

The core of the issue is that the way Pmw is packaged in panda (in the root panda dir under Pmw). The init.py file in that dir does a bunch of processing to find the best version of Pmw to install. This seems to require looking up directories and modifiying the python path on the fly.

The problem is that when py2exe packages up your code, it sticks everything in a zipfile which makes all of the directory lookup stuff not work as expected.

The maintainers of Pmw made a little script that fixes this issue by baking (they call it freezing) your current version of Pmw into one handy-dandy file called Pmw.py. THe script is called bundlepmw.py and you can get it in the ‘bin’ directory of the Pmw 1.2 distribution.

You can get it here.

http://pmw.sourceforge.net/

With this script in hand, I did the following to fix the issue:

ppython bundlepmw.py C:\Panda3d-1.3.2\Pmw_1_2\lib

This generates a “frozen” version of Pmw called Pmw.py file w/every thing you need

Then re-name the old C:\Panda3d-1.3.2\Pmw directory to something else (you dont’ need it anymore). Create a new directory called “Pmw” and put the Pmw.py file you generated in that directory as well as PmwBlt.py and PmwColor.py from the Pmw installation that comes w/Panda.

Now the Panda Specific part…

I had to modify :C:\Panda3D-1.3.2\direct\showbase\TkGlobal.py to make this work w/py2exe. Not quite sure why this works, but it does.

"""Undocumented Module"""

__all__ = ['taskMgr']

from Tkinter import *
from direct.task.TaskManagerGlobal import *
from direct.task.Task import Task
import Pmw
import sys

# This is required by the ihooks.py module used by Squeeze (used by
# pandaSqueezer.py) so that Pmw initializes properly

sys.modules['_Pmw'] = Pmw ##<--- I ADDED THIS LINE!!!

sys.modules['_Pmw'].__name__ = '_Pmw'
...

You also will probably need to update your PYTHONPATH environment variable to point at C:\Panda3D-1.3.2\Pmw.

Finally, in your py2exe setup script, make sure you add the Pmw directory to the package dir argument. There’s more info on setting up py2exe for python in the links I provided above.

Mine looks like this:

'':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'),
                'direct.showutil' : os.path.join(pandapath, 'direct/showutil'),
                'pandac' : os.path.join(pandapath, 'pandac'),
                'Pmw':os.path.join(pandapath, 'Pmw'),

so this would be a second way to distribute panda? cool thanks!