Hello All, I'm running into a strange problem on Leopard with how Python loads shared libraries. I'll give you a background of what we are trying to accomplish before describing the problem. I am not certain whether this is an OS X problem, or a Python problem, though it appears with the combination of the two.
We have swig wrapped C++ code. We used to require our users to set LD_LIBRARY_PATH to the directory containing the dynamic libraries because the swig generated .so needs to dynamically link in another .so. The dependency tree looks like the following: foo.py <--- performs a "from libs import _foo" libs/ <--- LD_LIBRARY_PATH required to point here | _foo.so | bar.so <-- _foo.so depends on me The dependency of bar.so can be taken care of by using $ORIGIN with -rpath (http://linuxreviews.org/man/ld.so/). On Mac OS X this is done by post-processing the shared library with install_name_tool (http://lapcatsoftware.com/blog/2007/08/11/embedding-frameworks-in-loadable-bundles/). Another design goal was to allow for the same directory structure to be NFS mounted in a heterogeneous environment. Then the magic of Python can choose the proper .so to load based upon introspection of the machine architecture and the Python version being used. So the directory structure becomes: foo.py <--- performs a "from libs import GetModule; _foo = GetModule('_foo')" libs/ | __init__.py <--- contains code for GetModule | arch-specific-directory/ | _foo.so | bar.so <-- _foo.so depends on me The GetModule function defined in libs/__init__.py looks like the following: DLLS = os.path.join(os.path.basename(__file__), "arch-specific-directory") <-- determined at runtime based on platform, compiler, and python version def GetModule(name): args = imp.find_module(name, [DLLS]) return imp.load_module(name, *args) This works great on Linux. LD_LIBRARY_PATH can even be set to a directory that contains a different (incompatible) _foo.so and python will force the correct .so to be loaded. However, there is a bug on OS X Leopard (maybe Tiger too, I haven't tested it). On OS X, when DYLD_LIBRARY_PATH (the OS X equivalent of LD_LIBRARY_PATH) is set to a directory that contains an identically named .so file imp.load_module pulls that .so file in. Even though the .so has been specified by an absolute filename. Running a simple test with the -v option of python shows the following: [EMAIL PROTECTED]/debug/wrappers/python$ ls -1 $DYLD_LIBRARY_PATH _foo.so bar.so [EMAIL PROTECTED]/debug/wrappers/python$ python -vc "import openeye.oeshape; from time import sleep; sleep(10)" <python importing modules> Python 2.5.1 (r251:54863, Jan 17 2008, 19:35:17) [GCC 4.0.1 (Apple Inc. build 5465)] on darwin Type "help", "copyright", "credits" or "license" for more information. # foo.pyc matches foo.py import foo # precompiled from foo.pyc import libs # directory libs # libs/__init__.pyc matches libs/__init__.py import libs # precompiled from libs/__init__.pyc dlopen("/Users/coleb/debug/wrappers/python/openeye/libs/osx-10.5-g++4.0-x86+x64-python2.5/_foo.so", 2); <--- This is the correct .so! import _foo # dynamically loaded from /Users/coleb/debug/wrappers/python/openeye/libs/osx-10.5-g++4.0-x86+x64-python2.5/_foo.so <python clean up> That appears to be working correctly at first glance. The argument to dlopen is the correct shared library. Unfortunately, either python or OS X is lying to me here. If I inspect the python process with OS X's Activity Monitor and look at the "Open Files and Ports" tab, it shows that the _foo.so shared library is actually the one located inside $DYLD_LIBRARY_PATH. So this problem may not be python's, but I place it here as a first shot (maybe I'm using the imp module incorrectly). Thanks, Brian -- http://mail.python.org/mailman/listinfo/python-list