假设mine.py想要导入moduleA和moduleB,但是moduleA和moduleB都尝试导入一个名为“moduleC”的模块。这是两个不同的模块,它们恰好都被命名为“moduleC”。运行mine.py时,取决于sys.path,moduleA或moduleB获取正确的“moduleC”,另一个得到惊喜,然后出现混乱。
如果moduleA和moduleB是由不同的作者编写的,我们都不是,我们最好不要修改这些模块。是否有任何解决方案可供mine.py的作者使用,不能修改moduleA或moduleB?
当您是moduleA或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?
我的具体案例
我想在Python调试器pdb下运行一个名为PyMOL的程序。不幸的是,PyMOL有一个“cmd.py”,它导入并与pdb导入的常用cmd冲突。
PyMOL安装的相关部分如下所示:
pymol/
__init__.py
cmd.py
通过执行__init__.py
来运行PyMOL。然后,此文件将cmd
导入为from pymol import cmd
。
根据BrenBarn指出的工作,到目前为止,我可以通过暂时从pdb
前面删除cmd
目录,让pymol
成功导入正确的sys.path
。之后,当PyMOL尝试导入其cmd
时,它崩溃了。不知何故,我需要在cmd
导入之前导入模块搜索中删除Python的PyMOL
,但是在导入pdb
之后。
最小例子
$ ls
pymol/
$ ls pymol/
__init__.py cmd.py
初始化的.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()")
试试吧
$ 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!
编辑:上面给出的方法现在似乎有效,但正如BrenBarn的回答所述,可能没有解决办法让所有第三方代码都不作为最初要求的问题进行修改。这是由于PyMOL中的怪癖。
答案 0 :(得分:2)
您的问题不仅仅在于导入,而在于您正在运行 __init__.py
作为脚本。运行脚本时,Python会将包含脚本的目录添加到sys.path
的前面,这会全局影响所有后续导入。
如果您直接运行不想修改的文件,则无法自定义任何内容。你不能做任何偷偷摸摸的sys.path
操作,除非你先运行自己的代码,按照你想要的方式设置路径。如果您导入该文件而不是运行它,您可以使用自己的代码来调整路径。
我怀疑这个问题在某种程度上是针对PyMOL的,不幸的是,在这方面似乎没有精心设计。查看源代码here,我发现PyMOL的__init__.py
包含许多自定义代码,可以执行import __main__
之类的奇怪操作,并检查正在运行的自身版本是否具有各种属性。您可以尝试使用该文件中的注释中描述的“不支持/实验”方法,该方法涉及导入PyMOL而不是运行它。我对PyMOL一无所知,所以我不知道它是如何工作的。
可能值得联系PyMOL的作者,建议他们解决这个问题。