use what to pack panda program into executable

i found that many people pack panda script using py2exe,are there any better utilites for packing.which you think is easier and better to use.thanks alot

packpanda works great for me

Every release of my program, I mostly rewrite all the python stuff in C++, then just compile it :wink:

Pyinstaller? Pypackage? I think Pyinstaller looks good. I’ve never tried it though.

Has anyone been successful with getting either pypackage or pyinstaller to create a panda exe? I have had difficulty trying to get it to work, and don’t really want to spend the time diving into their respective code base to figure out how they work if someone has already done so.

Just out of curiosity, how come you decided against using packpanda?

As I understand it, packpanda and these alternatives are very similar, but achieve the same goal by different means. Packpanda creates an installer which basically copies the required modules into a directory and provides a .bat file to run the actual code. PyInstaller and pyPackage both extend py2exe, which grabs all the modules as well, but instead of a .bat file, it creates a .exe based off the input scripts. I am in need of a .exe file for special purposes, and have tried (unsuccessfully) to get a basic “compile” out of anything but packpanda. Any help would be appreciated.

Interesting. Sounds tricky to get it to work, though. It seems like this EXE file would need to contain all the 3D models and textures. Would these get extracted to a temporary directory when you run the EXE? If not, how would panda read them? If so, how would panda know to look inside the temporary directory?

If this special purpose is hiding your code then py2exe won’t help you much.

Py2exe creates a small .exe which launches a python interpreter, and then loads your .pyc files and executes them. The .pyc files will be either in a zip-file which is part of your distribution, or if you pass zipfile=None as an argument in setup.py then it will be appended to the small .exe. In both ways it is possible to extract the .pyc files with a few lines of Python code or your default zip programs.

In my opinion it is not worth too much fuzz to pack with py2exe, since someone who knows how to decomp(y)le Python bytecode will be able to locate the .pyc bytecode, no matter if it is zipped somewhere or just laying around. And packpanda has an option to distribute only .pyc files.

I have not tried the two installers from above, but if I get this right they are two-stage solution, which use py2exe first to create a “binary distribution”, and then package everything up into a single-file installer.

I have been able to use py2exe to compile simple test application. But this is some time ago, and with previous versions of Panda3D. But I had to tweak both with py2exe setup files, and with the Panda3D installation. Something I guess neither PyInstaller nor PyPackage can do automatically.

So if you really want to go the py2exe way, I suggest you try to compile with py2exe only first, and later find a way to package your “binary” distribution.

ennox

I have been curious if py2exe still can be used to “compile” Panda3D application. And yes, it is still possible, but still only with small modifications to the Panda3D installation.

This is my test application. It just loads a model (a 1x1x1 cube, with a texture “wood.png”), register one key event, and nothing else:

import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject

class World( DirectObject ):

    def __init__( self ):
        base.setBackgroundColor( 0.1, 0.2, 0.5, 0 )
        self.accept( 'escape', self.exit )

        np = loader.loadModel( 'models/cube.egg' )
        np.reparentTo( render )
        np.setPos( 0, 5, 0 )
        np.setH( 45 )
        np.setP( 15 )

    def exit( self ):
        taskMgr.stop( )

world = World( )
run( )

And this is how I compiled it with py2exe:

(1) Tweak the Panda3D 1.4.0 installation: Goto directory “…/Panda3D-1.4.0/direct” and

  • copy anything from “./src” to this directory
  • edit init.py: comment all lines

(2) Install py2exe 0.6.6, where ppython.exe can find it. For example in the Panda3D site-packages.

(3) Create a setup.py file:

setup( windows = [ { 'script' : 'game.py',
                     #'icon_resources' : [ ( 1, 'game.ico' ) ],
                     } ],
       zipfile = None,
       options = { 'py2exe': { 'optimize' : 2,
                               'excludes' : [ 'Tkinter' ] },
                 },
       data_files = [ ( 'models', [ 'models/cube.egg', 'models/wood.png' ] ), 
                      ( 'etc', [ 'etc/Config.prc', ] ),
                    ],
       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'), 
                    },
)

(4) Compile:

> ppython setup.py py2exe

Be aware that the binary distribution is rather large, about 39M. But the bulk of the distribution is Panda3D .dll files, and you can compress them to about 13M (33%!!!) using upx.

cho off

Rem ____py2exe____
ppython setup.py py2exe -a

Rem ____upx____
cd dist
copy avcodec-51-panda.dll ..\build\avcodec-51-panda.dll
..\upx301.exe --best *.*
copy ..\build\avcodec-51-panda.dll avcodec-51-panda.dll
cd ..

Rem ____clean up____
rd build /s /q

@Yosh: is there a particular reason to have the “src” directory in “Panda3D-1.4.0/direct” ? Everything seems to work fine if I move “direct/src/" to "direct/” and make “direct/init.py” an empty file.

enn0x

The src has been part of the CVS tree for a long time (before my time). As I understand it, I’m actually supposed to remove it when I package up a panda distribution. I just never got around to implementing that.

At the moment, I want an exe to be able to then create a screensaver, as well as be able to call the panda program from other, simpler languages. Also, I noticed both pyPackage and Pyinstaller allow you to remove the msdos prompt, and just open the panda window.

Ennox, they do not have installer packages with them. Both programs only create an exe. Both are supposed to have better module-finding techniques as well as special options like removing the msdos window or changing the icon. They both can get rid of the zip file that py2exe creates, moving those files into regular folders. There are probably other things, but these are the “features” I noticed off the bat. Bye the way, Thanks for your code and suggestions for py2exe, they have helped a bunch.

Hmm… you are right with PyInstaller. PyInstaller uses a selfwritten loader (Just a few lines of C code) to extract any resources to a working directory right after starting the .exe, and then calls Python from C. I had a short glance at the coude, but didn’t work through it. Looks interesting.

But PyPackage is built on top of py2exe, according to their site:

About the MSDOS prompt, the icon and the zipfile: py2exe has these features already. Look at the first lines of the setup.py file:

setup( windows = [ { 'script' : 'game.py',
                     #'icon_resources' : [ ( 1, 'game.ico' ) ],
                     } ],
       zipfile = None,
...

icon: I did comment the line that tells py2exe to use a custom icon, just uncomment it and provide a nice icon resource. Might be you have to refer to the py2exe documentation to find out what icon formats are supported if there are any problems.

MSDOS prompt: You will only see a console if you use “console = [ {…”. If you use " windows = [ {" then there won’t be a console, just the Panda3D window (or wxFrame or whatever main window your application creates).

zip-file: The line “zipfile = None,” is where you get rid of the zipfile.

So if it is just these three features then maybe py2exe might be able to do what you want.
enn0x

Thanks, Enn0x. I had just one question about py2exe: Where should I put other user created scripts? I have put them in the Data Files, the Windows, and the packages/package_dir, and they all work just fine. Is there a correct way to do it?

Maybe a language barrier (English is not my native language). I don’t understand what you mean with “other user created scripts”. Scripts like for example the chicken exporter for Blender? A script that get created and/or modified by the user of your application AFTER he/she installed your application?

When using py2exe you have to be careful with relative file path, since some of Python’s environment variables are different if running from and .exe, for example sys.argv[0] or sys.executable. This is a typical way to find out the path of your main script:

 def getMainDir( ):
    frozen = ( hasattr( sys, 'frozen' ) or    # new py2exe
               hasattr( sys, 'importers' )    # old py2exe
             or imp.is_frozen( '__main__' ) ) # tools/freeze

    if frozen:
        return os.path.dirname( sys.executable )
    else:
        return os.path.dirname( sys.argv[0] )

A wild guess would be to use data_files, since packages/package_dir is just an additional hint for py2exe where to look for modules imported by your code. Normally it is not necessary to use packages/package_dir, since py2exe finds (almost) anything. And “windows --> script” should point to the script that launches your application. Typical names are main.py or game.py (packpanda requires you to use game.py by the way).

enn0x

Sorry, nothing as complicated as that. I just meant other scripts that you (the programmer) creates for the game/tool but is not the main (starting) script. I figured out that you don’t have to do anything to the setup, py2exe will find it for you. Thanks anyway, and for the relative path finding.

Sorry, I have another question. Is there a way using py2exe to move the dll’s and the .pyd’s into a subfolder or the zip file? It seems as though this should be possible because the exe uses loadlibrary(‘filepath’), but I have not succeeded to do so…(but then again, I am new to py2exe…)

Hmm… I don’t know. I’m not an expert on py2exe either, just used it a few times. LoadLibrary is on the C/C++ level, so subclassing py2exe to customize the build process probably doesn’t work.

You could try these first:
(1) modify the output of py2exe by hand. E.g. move the .dll’s and .exe to a subdirectory and create a bat file in the main directory that launches the .exe.
(2) ask on the py2exe mailing list for help. If anybody knows then the creators of py2exe.

And about adding more files/data to the executable - maybe this can help you:
http://www.py2exe.org/index.cgi/CustomDataInExe

enn0x

After couple of tries I got in working with “auto-py-to-exe”. Lets take this as an example Example
run “auto-py-to-exe” GUI and basically you have to go under “Additional Files” click “Add Folder” and search for the panda module folder that you are using for example for “from direct.showbase.ShowBase import ShowBase” the location its in “YOUR_PYTHON_FOLDER/Lib/site-packages/direct”, for panda3d module its in “YOUR_PYTHON_FOLDER/Lib/site-packages/panda3d” and you also have to go under “Advance” to “–paths” and add folder “YOUR_PYTHON_FOLDER/Lib/site-packages/panda3d” because u else will get this annoying error:
Error
This error basically tell you that the file already exist and should not be created again, so add under
“–paths” and add the folder with the file that gives you error. Hope this helped! First 2021 post :smiley: