Pyinstaller not working with Panda3D – 'direct' module not found

I’m working through some Panda3D tutorials and have created a few simple programs. At some point in the near future, I would like to be able to bundle my Panda3D program into a standalone application using PyInstaller.

However, I’m experiencing a strange issue even with the simplest program.

I’ve used the command pyinstaller -F -c -w 01\ –\ blank\ window.py.

It works as normal and creates a Unix executable and a macOS .app file in the dist folder. However, neither of them work, they just open and close immediately. After some research, I found the source of the problem.

When I run either executable from Terminal, I get this error:

Traceback (most recent call last):
  File "01 – blank window.py", line 1, in <module>
    from direct.showbase.ShowBase import ShowBase
ModuleNotFoundError: No module named 'direct'
[29403] Failed to execute script 01 – blank window

I don’t know why this error is occurring, given that my programs work perfectly fine when using python3 01\ –\ blank\ window.py or running straight from VS Code.

How can I fix the above error?

Specs:

macOS 10.14.6 (Mojave)

My system has Python 2.7 (comes with macOS) and Python 3.7. I always use Python 3.7. Though I’m not sure what version of Python I’m using with Panda3D, since the SDK comes with its own version.

Panda3D 1.10.4.1

The direct module is at /Developer/Panda3D/direct and my PATH is /Library/Frameworks/Python.framework/Versions/3.7/bin://anaconda3/condabin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/akaash_home/Library/Python/3.7/bin:/Developer/Panda3D/bin

Also, I wonder if it makes a difference that I’m running these files off an external hard drive and I’m using PyInstaller to put the app on the same drive.

EDIT:

I’ve also tried adding the option --hidden-import=direct but it makes no difference.

I’m wondering whether PyInstaller isn’t perhaps using Python 2, instead of Python 3. I fear that I don’t know how to check or change this, myself, but perhaps it will give you an avenue of investigation.

I have considered that, but I also don’t know how to find out. I guess I have some searching to do.

I’m not sure if this is the right check, but I’ve tried running some Panda3D programs from the Terminal using python3 file.py and they all work fine, which suggests that Panda3D is comfortably using Python 3.

Also, this link seems to suggest that the more recent versions of Panda3D use Python 3 quite well: Python 3 Support

To make sure that the version of pyinstaller is using the same build of Python as your panda3d installation, try running it with python -m pyinstaller (where instead of python you use the same command you use to run Panda3D).

That said, it’s possible pyinstaller just needs a hint to point it to the location of the Panda3D libraries. Try looking in the command-line options for pyinstaller.

I’ve tried python3 -m pyinstaller -F -c -w 01\ –\ blank\ window.py if that’s what you mean and it returned the error /Library/Frameworks/Python.framework/Versions/3.7/bin/python3: No module named pyinstaller.

If I run python3 -m pip install pyinstaller or python3 -m pip install --user pyinstaller, it says Requirement already satisfied, so I know it’s properly installed and the messages show it works with Python 3.7.

When I run a Panda3D file from VS Code, the Terminal command it uses also specifies Python 3.7, so everything seems to match up.

I have no idea why it’s not working.

I’ve found out a way to do it that works. I just copied the direct and panda3d modules to the same directory where the 01 – blank window file lies. PyInstaller is now able to find those modules.

However, it’s now coming up with another error:

ImportError: dlopen(/Volumes/iMac and MBP Files/Programming/Python/Panda3D/Tutorials from the Manual/dist/01_blank_window/panda3d/core.cpython-37m-darwin.so, 2): Library not loaded: @loader_path/../libp3interrogatedb.1.10.dylib
Referenced from: /Volumes/iMac and MBP Files/Programming/Python/Panda3D/Tutorials from the Manual/dist/01_blank_window/panda3d/core.cpython-37m-darwin.so
Reason: image not found

Any ideas on how to solve this?

I know where the libp3interrogatedb.1.10.dylib library is and I’ve copied it into various places around the folders produced by PyInstaller, but I guess my luck has run out.

Also, even though I’ve fixed the direct and panda3d module issue, is there any other way I can get it to work without having to copy the required modules into the .py file directory?

I’ve looked at the PyInstaller command-line options and nothing else seems to work.

So I’ve come up with a way to sort out this new ImportError, which is to copy over EVERYTHING to do with Panda3D into the .py file directory. Now PyInstaller can find what it needs. But now I’m getting this error:

Exception: No graphics pipe is available!
Your Config.prc file must name at least one valid panda display
library via load-display or aux-display.

I looked at this link: No graphics pipe available and they suggested there may be a line missing in the Config.prc file, namely the load-display line, but I’ve checked the file and that line is indeed there.

I have these lines in the config file:

load-display pandagl
aux-display pandadx9
aux-display pandagles
aux-display p3tinydisplay

Is there an earlier error message that you have not shared? It seems that either it cannot find the etc/Config.prc file (which needs to be copied over), or it can’t find the libpandagl.so plug-in.

Out of curiosity, is there a good reason you are not just using our own deployment system?

Those are all the error messages I’ve had.

I read another page where someone suggested typing in the Python Shell something like:

from pandac.PandaModules import *

print(ConfigPageManager.getGlobalPtr().getSearchPath())

and it returned:

/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/panda3d/etc

(Even though this worked, I am aware that pandac.PandaModules is deprecated.)

Also, when I type:

print(ConfigPageManager.getGlobalPtr())

I get:

0 explicit pages:

2 implicit pages:
  /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/panda3d/etc/Config.prc
  /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/panda3d/etc/Confauto.prc`

Does this mean it is able to find the Config.prc file?

I don’t know a similar check for libpandagl.so, but all I know is that everything runs fine until I use PyInstaller.

What is your deployment system?

I’ve read about PackPanda but I heard that’s no longer supported, unless it’s something else.

That would be amazing if there were another deployment system that worked just as easily as Panda3D!

The new deployment system uses “setuptools”, and in my experience seems to work quite well! :slight_smile:

I have a tutorial that, amongst other things, covers the basic usage of the new deployment system. If you don’t mind jumping in near the end of the tutorial, you may find it to be a useful introduction.

(You could just go through the whole tutorial, of course. But if you just want to learn about the new deployment system, then this one part should be fine, I think; while it may have references to previous parts, I don’t think that it relies on them too heavily.)

You should find it here:

I think that the manual has a more -detailed and -in-depth discussion of the subject, starting here:

http://www.panda3d.org/manual/?title=Distributing_Panda3D_Applications

Wow! I’ve just followed your tutorial (with a bit of help from the manual) and it works!

Initially there was an issue where setuptools worked and produced the distributable apps, but they weren’t opening because they weren’t able to find the .egg files. In my main.py files, in the loadModel function, I only used relative paths, but when I switched to absolute paths, that resolved the issue.

Now all I have to do is see that they work on other platforms…

Thank you so much!

Update:

It turns out I didn’t need to change the file path to absolute. All I needed to do was create a models directory in the same folder as main.py and put the relevant model(s) in that directory. Then if I change the file path back to relative, all works well!

I’m glad that it seems to have helped! :slight_smile: