Suppose mine.py wants to import moduleA and moduleB but moduleA and moduleB each try to import a module called "moduleC". These are two distinct modules that both happen to be named "moduleC". When mine.py is run, depending on sys.path either moduleA or moduleB gets the correct "moduleC", the other gets a surprise, and chaos ensues.
If moduleA and moduleB were written by different authors, neither of which is us, it is preferable to not modify those modules. Is there any solution available to the author of mine.py that does not modify moduleA or moduleB?
The following questions ask how to solve this issue when you are the author of moduleA or moduleB.
Importing from builtin library when module with same name exists
How to access a standard-library module in Python when there is a local module with the same name?
My specific case
I want to run a program called PyMOL under the Python debugger, pdb. PyMOL unfortunately has a "cmd.py" that it imports and that conflicts with the usual cmd which pdb imports.
The relevant parts of the PyMOL install look like this:
pymol/
__init__.py
cmd.py
PyMOL is run by executing __init__.py
. This file then imports cmd
as from pymol import cmd
.
Working from what BrenBarn pointed out, so far I can get pdb
to successfully import the correct cmd
by temporarily removing the pymol
directory from the front of sys.path
. After that when PyMOL tries to import its cmd
it crashes. Somehow I need to remove Python's cmd
from the import module search before PyMOL
imports but after pdb
imports.
Minimal example
$ ls
pymol/
$ ls pymol/
__init__.py cmd.py
init.py
# insert some code into __init__.py directly
import sys
pymol_path = sys.path[0]
sys.path[0] = ""
import pdb
sys.path[0] = pymol_path
from pymol import cmd
# test a sandwich of calls that require each "cmd" modules
pdb.set_trace()
cmd.foo()
pdb.set_trace()
cmd.foo()
print "done!"
# original PyMOL __init__.py code would follow
cmd.py
def foo():
print("cmd.foo()")
Try it
$ PYTHONPATH= python ./pymol/__init__.py
> /Users/khouli/scr/pymol_scr/pymol/__init__.py(11)<module>()
-> cmd.foo()
(Pdb) continue
cmd.foo()
> /Users/khouli/scr/pymol_scr/pymol/__init__.py(13)<module>()
-> cmd.foo()
(Pdb) continue
cmd.foo()
done!
Edit: The method given above now seems to work but as BrenBarn's answer states, there likely is no solution that leaves all third party code unmodified as the question originally asked for. This is due to quirks in PyMOL.