是否可以使用两个具有相同名称的Python包?

时间:2011-02-21 05:50:57

标签: python import packages

我对进口有疑问。这个问题似乎有点人为,但其目的是探讨在包中使用绝对导入对所有导入的限制。 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。但是改变任一包目录的内容都不行。

5 个答案:

答案 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.mod1import pkg2.mod1

答案 3 :(得分:0)

否,但是您可以使用关键字“ as”并根据需要重命名程序包名称。 EG:

from tableaudocumentapi import Workbook as table

答案 4 :(得分:-4)

为什么要首先导入两个不同版本的软件包?我看到这是你所有问题的根源。

我建议改写你的代码并使用最新的软件包。