Using the imp module with a web deployed p3d file

Hi all,

Just trying to build a project at the moment and running into an error I haven’t seen before. If anyone has any ideas I would really appreciate a hand here!

I’m wondering if the problem is something to do with the dynamic loading of modules I’m doing in this project with imp.find_module.

On a related note - will imp.find_module work in a p3d file distributed via the web?

:AppRunner: Total Panda3D disk space used: 162 MB
:AppRunner: Configured max usage is: 2048 MB
Traceback (most recent call last):
  File "C:\buildslave\release_rtdist_win32\build\panda3d\built_cmu\direct\showbase\Messenger.py", line 415, in __taskChainDispatch
  File "C:\buildslave\release_rtdist_win32\build\panda3d\built_cmu\direct\showbase\Messenger.py", line 473, in __dispatch
  File "C:\buildslave\release_rtdist_win32\build\panda3d\built_cmu\direct\p3d\AppRunner.py", line 745, in __startIfReady
  File "VFSImporter", line 153, in load_module
  File "/Users/buildbot/slave/release_rtdist_osx/build/panda3d/built_cmu/direct/p3d/packp3d.py", line 219, in <module>
  File "/Users/buildbot/slave/release_rtdist_osx/build/panda3d/built_cmu/direct/p3d/packp3d.py", line 209, in makePackedApp
  File "/Users/buildbot/slave/release_rtdist_osx/build/panda3d/built_cmu/direct/p3d/Packager.py", line 2705, in endPackage
  File "/Users/buildbot/slave/release_rtdist_osx/build/panda3d/built_cmu/direct/p3d/Packager.py", line 437, in close
  File "/Users/buildbot/slave/release_rtdist_osx/build/panda3d/built_cmu/direct/p3d/Packager.py", line 539, in installMultifile
  File "C:\buildslave\release_rtdist_win32\build\panda3d\built_cmu\direct\showutil\FreezeTool.py", line 860, in done
  File "C:\buildslave\release_rtdist_win32\build\panda3d\built_cmu\direct\showutil\FreezeTool.py", line 950, in __loadModule
  File "C:\buildslave\release_rtdist_win32\build\panda3d\built_cmu\direct\showutil\FreezeTool.py", line 1402, in load_module
  File "c:\python26\lib\modulefinder.py", line 305, in load_module
    self.scan_code(co, m)
  File "c:\python26\lib\modulefinder.py", line 414, in scan_code
    self._safe_import_hook(name, m, fromlist, level=level)
  File "c:\python26\lib\modulefinder.py", line 323, in _safe_import_hook
    self.import_hook(name, caller, level=level)
  File "c:\python26\lib\modulefinder.py", line 125, in import_hook
    parent = self.determine_parent(caller, level=level)
  File "c:\python26\lib\modulefinder.py", line 162, in determine_parent
    parent = self.modules[pname]
KeyError: 'scripts'
:task(error): Exception occurred in PythonTask Messenger-default
Traceback (most recent call last):
  File "C:\buildslave\release_rtdist_win32\build\panda3d\built_cmu\direct\p3d\AppRunner.py", line 636, in run
  File "C:\buildslave\release_rtdist_win32\build\panda3d\built_cmu\direct\task\Task.py", line 502, in run
  File "C:\buildslave\release_rtdist_win32\build\panda3d\built_cmu\direct\task\Task.py", line 460, in step
  File "C:\buildslave\release_rtdist_win32\build\panda3d\built_cmu\direct\showbase\Messenger.py", line 415, in __taskChainDispatch
  File "C:\buildslave\release_rtdist_win32\build\panda3d\built_cmu\direct\showbase\Messenger.py", line 473, in __dispatch
  File "C:\buildslave\release_rtdist_win32\build\panda3d\built_cmu\direct\p3d\AppRunner.py", line 745, in __startIfReady
  File "VFSImporter", line 153, in load_module
  File "/Users/buildbot/slave/release_rtdist_osx/build/panda3d/built_cmu/direct/p3d/packp3d.py", line 219, in <module>
  File "/Users/buildbot/slave/release_rtdist_osx/build/panda3d/built_cmu/direct/p3d/packp3d.py", line 209, in makePackedApp
  File "/Users/buildbot/slave/release_rtdist_osx/build/panda3d/built_cmu/direct/p3d/Packager.py", line 2705, in endPackage
  File "/Users/buildbot/slave/release_rtdist_osx/build/panda3d/built_cmu/direct/p3d/Packager.py", line 437, in close
  File "/Users/buildbot/slave/release_rtdist_osx/build/panda3d/built_cmu/direct/p3d/Packager.py", line 539, in installMultifile
  File "C:\buildslave\release_rtdist_win32\build\panda3d\built_cmu\direct\showutil\FreezeTool.py", line 860, in done
  File "C:\buildslave\release_rtdist_win32\build\panda3d\built_cmu\direct\showutil\FreezeTool.py", line 950, in __loadModule
  File "C:\buildslave\release_rtdist_win32\build\panda3d\built_cmu\direct\showutil\FreezeTool.py", line 1402, in load_module
  File "c:\python26\lib\modulefinder.py", line 305, in load_module
    self.scan_code(co, m)
  File "c:\python26\lib\modulefinder.py", line 414, in scan_code
    self._safe_import_hook(name, m, fromlist, level=level)
  File "c:\python26\lib\modulefinder.py", line 323, in _safe_import_hook
    self.import_hook(name, caller, level=level)
  File "c:\python26\lib\modulefinder.py", line 125, in import_hook
    parent = self.determine_parent(caller, level=level)
  File "c:\python26\lib\modulefinder.py", line 162, in determine_parent
    parent = self.modules[pname]
KeyError: 'scripts'
Failure on startup.

EDIT: Fixed subject header.

After a bit of digging I was able to narrow down the problem. It seems packp3d doesn’t like scripts any deeper than the start level which aren’t referenced anywhere using import. I was able to fix the problem by dumping all my scripts into the project root directory.

This has exposed a different problem however - I want to use imp.find_module() to load libraries at runtime for a p3d file on a web page, but the code can’t seem to find them once I’ve packed to a p3d file. Seems like sys.path is changed in the runtime environment to C:\Users<your name>\AppData\Local\Panda3D, and even though on inspection the module I want to load exists at C:\Users<your name>\AppData\Local\Panda3D\start, imp still won’t find it.

How do I go about fixing this issue? Should I omit modules I’m planning on importing with imp from the pack process, then add them to the multifile afterwards? Or will uploading the modules to the same directory as my p3d file work?

I’m not entirely sure what you’re describing. It’s true that packp3d won’t find scripts that aren’t referenced by an import anywhere, because it uses the modulefinder to find all the relevant scripts, and modulefinder simply scans your code and looks for literal import statements. If you have code loaded from a dynamic directory that you want packp3d to find, you’ll have to switch to ppackage instead, and then you can explicitly add it to the modulefinder or to sys.path in the pdef file.

At runtime, you can extend sys.path yourself to include the current directory (which is the “start” directory) if you want to load a python file that you just downloaded and put there.

David

Thanks for the response, David. Just to clarify: I’m trying to build a project that looks like this:

c:/myProject/
    main.py
    myModule.py

however once built with packp3d this code in main.py:

imp.find_module( 'myModule' )

gives me:

ImportError: No module named myModule

whereas this works as expected when running interactively.

So you’re suggesting that I shouldn’t build with packp3d but instead use ppackage and add ‘myModule.py’ explicitly. Then find_module( ‘myModule’ ) should work so long as base.mainDir or base.appRunner.multifileRoot is in sys.path. Does this sound right?

EDIT: Sounds like I use ppackage in conjunction with packp3d: the latter for the main app then the former to create a downloadable package my app will look for…

Yes, using ppackage, you can explicitly add myModule.py to the p3d file, and then you should be able to find it with imp.find_module(). Or, you can also just put code like this in your main.py file:

if False:
    import myModule

Of course this code won’t actually import myModule, but modulefinder will think it does, and then packp3d will add myModule.py to your p3d file.

David

Hi David,

Finally got around to trying ppackage but still not having much luck. So far the p3d file is generated fine but imp is still raising an exception. I’ve got my p3d runtime to print out all the files on sys.path and “myModule.pyo” is listed there inside the runtime directories.

I might try a simpler version to better understand the problem, but is there anything else you can think of why this might not work?

Thanks in advance!