2

假设 mine.py 想要导入 moduleA 和 moduleB,但是 moduleA 和 moduleB 都尝试导入一个名为“moduleC”的模块。这是两个不同的模块,它们都恰好被命名为“moduleC”。当 mine.py 运行时,根据 sys.path 模块A 或模块B 得到正确的“模块C”,另一个得到一个惊喜,随之而来的是混乱。

如果 moduleA 和 moduleB 是由不同的作者编写的,而不是我们,最好不要修改这些模块。mine.py 的作者是否有任何不修改模块A 或模块B 的解决方案?

以下问题询问当您是 moduleA 或 moduleB 的作者时如何解决此问题。

存在同名模块时从内置库导入

当有同名的本地模块时,如何在 Python 中访问标准库模块?

我的具体情况

我想在 Python 调试器 pdb 下运行一个名为 PyMOL 的程序。不幸的是,PyMOL 有一个它导入的“cmd.py”,它与 pdb 导入的常用 cmd 冲突。

PyMOL 安装的相关部分如下所示:

pymol/
    __init__.py
    cmd.py

PyMOL 通过执行__init__.py. 该文件然后导入cmdfrom pymol import cmd.

pdb根据BrenBarn 指出的内容,到目前为止,我可以cmd通过暂时pymolsys.path. 之后,当 PyMOL 尝试导入它时,cmd它会崩溃。不知何故,我需要在导入之前但在导入之后cmd从导入模块搜索中删除 Python 。PyMOLpdb

最小的例子

$ 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

命令文件

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 中的怪癖。

4

1 回答 1

2

您的问题不仅在于导入,还在于您作为脚本运行。 __init__.py当您运行脚本时,Python 会将包含该脚本的目录添加到 的前面sys.path,这会全局影响所有后续导入。

如果您直接运行不想修改的文件,则无法自定义任何内容。你不能做任何偷偷摸摸sys.path的操作,除非你首先运行你自己的代码,以你想要的方式设置路径。如果您导入文件而不是运行它,您可以使用自己的代码来调整路径。

我怀疑这个问题在某种程度上是 PyMOL 特有的,不幸的是,它在这方面似乎没有经过精心设计。查看这里的源代码,我看到 PyMOL__init__.py包含许多自定义代码,这些代码会做一些奇怪的事情import __main__,例如检查正在运行的自身版本是否具有各种属性。您可以尝试使用该文件注释中描述的“不支持/实验性”方法,该方法涉及导入 PyMOL 而不是运行它。我对 PyMOL 一无所知,所以我不知道它是如何工作的。

可能值得联系 PyMOL 的作者建议他们解决这个问题。

于 2014-11-20T04:47:45.000 回答