Setuptools: Can sys.path be modified?

Recently I moved all my third-party modules to an directory external to my source directory, so I have something like this :

/ main.py
 ... /myapp/ ...
 .... /third-party/...

In my main.py I added the following line to add third-party to the paths where Python looks for modules to be imported :

[’/Users/ld/git/3D/cosmonium/build/macosx_10_6_x86_64/cosmonium.app/Contents/MacOS/…/Frameworks’]

sys.insert(0, 'third-party')

It probably isn’t the most elegant way, but it works :slight_smile:

However now when I build a binary version of the app, the app crashes:

    from panda3d.core import LPoint3d, LVector3d, LVector3, LQuaternion, LQuaterniond, LColor, BitMask32
  File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/importlib/_bootstrap.py", line 983, in _find_and_load
    return _find_and_load_unlocked(name, import_)
  File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/importlib/_bootstrap.py", line 967, in _find_and_load_unlocked
    module = _load_unlocked(spec)
  File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/importlib/_bootstrap.py", line 677, in _load_unlocked
    spec.loader.exec_module(module)
  File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/importlib/_bootstrap.py", line 819, in exec_module
    exec(code, module.__dict__)
  File "panda3d.core", line 1, in 
  File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/imp.py", line 342, in load_dynamic
    return _load(spec)
  File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/importlib/_bootstrap.py", line 696, in _load
    return _load_unlocked(spec)
  File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/importlib/_bootstrap.py", line 670, in _load_unlocked
    module = module_from_spec(spec)
  File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/importlib/_bootstrap.py", line 583, in module_from_spec
    module = spec.loader.create_module(spec)
  File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/importlib/_bootstrap_external.py", line 1043, in create_module
    _imp.create_dynamic, spec)
  File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/importlib/_bootstrap.py", line 219, in _call_with_frames_removed
    return f(*args, **kwds)
ImportError: dlopen(third-party/panda3d.core.so, 2): image not found

If I print the content of sys.path before and after my insert, I see that the path to the .so libraries is still there :

Before:

['/Users/ld/git/cosmonium/build/macosx_10_6_x86_64/cosmonium.app/Contents/MacOS/../Frameworks']

After

['third-party', '/Users/ld/git/cosmonium/build/macosx_10_6_x86_64/cosmonium.app/Contents/MacOS/../Frameworks']

So it seems that the importer does not tries all the paths but only check the first entry, (or raise an exception that is not catched in the loop over sys.path)

Apparently in FreezeTool.py, we use sys.path[0] to indicate something in particular when writing out the code for the panda3d.core module:

if self.platform.startswith("macosx") and not use_console:
    # We write the Frameworks directory to sys.path[0].
    code = 'import sys;del sys.modules["%s"];import sys,os,imp;imp.load_dynamic("%s",os.path.join(sys.path[0], "%s%s"))' % (moduleName, moduleName, moduleName, modext)

Try using sys.path.insert(1, path) instead.

Maybe we should instead be putting the Frameworks path elsewhere rather than expecting it to be at a certain location in sys.path (maybe an underscore-prefixed variable on sys, or so).

Thanks, it works fine, though now I need an even bigger comment before the code to explain why it is insert(1, …) :slight_smile: