我对进口有疑问。这个问题似乎有点人为,但其目的是探讨在包中使用绝对导入对所有导入的限制。 PEP8强烈反对相对导入(编辑:Google Python Style Guide表示永远不要使用它们。)
假设您有两个大型包,它们都具有相同的名称,并且都根据PEP8使用绝对导入:
/pkg1 mod1.py (contains an absolute import: 'import pkg1.mod2') mod2.py ... /pkg1 mod1.py (contains an absolute import: 'import pkg1.mod3') mod3.py ...
还要说你正在开发一个你想要使用这两个包的Python项目。例如,如果您想在项目中使用同一个包的两个版本,可能会出现这种情况。
有没有办法将两个包合并到项目层次结构中,以便您可以在整个项目中自由使用两个包中的模块?
对于解决方案,可以使用导入别名和临时修改sys.path。但是改变任一包目录的内容都不行。
答案 0 :(得分:10)
简短的回答是否定的,Python不接受两个具有相同名称的包。 (有些名为“命名空间包”的东西允许在多个目录上实现单个包,但它们需要将所涉及的包设置为相互协作)。
PEP 8阻止显式相对导入的方式是其更值得怀疑的建议之一,正是因为它使重命名包以避免命名冲突变得更加困难。如果这两个包使用相对导入,你可以重命名其中一个或将它嵌套在另一个包中并完成它。
导入别名在这里没有帮助,因为它最终在sys.modules
中的名称是重要的,并且使用模块的名称作为导入,而不是最终被绑定的名称导入模块。
如果你想变得异国情调,你可以编写自己的导入器(参见PEP 302和3.x importlib
documentation)。如果你决定走那么远,你可以做任何你想做的事情。
答案 1 :(得分:2)
我的初步测试(在Python 2.6和3.1中)表明以下内容可能有效:
import sys, re
import foo as foo1
for k in sys.modules:
if re.match(r'foo(\.|$)', k):
newk = k.replace('foo', 'foo1', 1)
sys.modules[newk] = sys.modules[k]
# The following may or may not be a good idea
#sys.modules[newk].__name__ = newk
del sys.modules[k]
sys.path.insert(0, './python')
import foo as foo2
for k in sys.modules:
if re.match(r'foo(\.|$)', k):
newk = k.replace('foo', 'foo2', 1)
sys.modules[newk] = sys.modules[k]
# The following may or may not be a good idea
#sys.modules[newk].__name__ = newk
del sys.modules[k]
但是,我只针对非常简单的包进行了测试,并且仅仅将其作为好奇心进行了尝试。一个问题是它可能会中断reload
。 Python实际上并不是设计用于处理具有相同顶级名称的多个包。
此时,我暂时会说这在一般情况下是不可能的,尽管在某些有限的情况下它是可能的,但它非常脆弱。
答案 2 :(得分:0)
实际上,您应该使用命名空间(包)来正确分隔您最终要使用的模块。在上面的代码中。
/pkg1
mod1 - can just import mod2
mod2.py
__init__.py
/pkg2
mod1 - can just import mod2
mod2.py
__init__.py
在其他地方,您应该根据需要import pkg1.mod1
或import pkg2.mod1
。
答案 3 :(得分:0)
否,但是您可以使用关键字“ as”并根据需要重命名程序包名称。 EG:
from tableaudocumentapi import Workbook as table
答案 4 :(得分:-4)
为什么要首先导入两个不同版本的软件包?我看到这是你所有问题的根源。
我建议改写你的代码并使用最新的软件包。