Python - 引用的包是其他包的属性

时间:2014-02-04 20:43:33

标签: python import packages relative-import

如何让一个包引用另一个包,但让它看起来像引用的包属于初始包?

package_1
|
|____ __init__.py

package_2
|
|____ __init__.py
|____ module_1.py

在package_1.__init__.py中

# __init__.py
import package_2

现在以下调用正常:

>>> import package_1
>>> print package_1
<module <module 'package_1' from  '...\package_1\__init__.pyc'>

>>> from package_1 import package_2
>>> print package_2
<module 'package_2' from '...\package_2\__init__.pyc'>

>>> print package_2.module_1
<module 'package_2.module_1' from '...\package_2\module_1.pyc'>

>>> from package_2 import module_1
>>> print module_1
<module 'package_2.module_1' from '...\package_2\module_1.pyc'>

但我希望能够做到这一点:

>>> from package_1.package_2 import module_1

但我明白了:

Traceback (most recent call last):
    File "testfile.py", line 15, in <module>
        from package_1.package_2 import module_1
ImportError: No module named package_2

我想这样做的原因是因为package_2曾经是package_1的子包。现在package_2是它自己的包,我希望能够从package_1引用它以保持之前的行为。

1 个答案:

答案 0 :(得分:1)

您可以在package_2.py下添加一个仅包含以下内容的package_1模块:

from package_2 import *

如果您使用的是python2,则应添加:

from __future__ import absolute_import

在文件的顶部以获得python3的行为。

这样package_1.package_2与<{1}}的不同,即:

package_2

然而 import package_1.package_2 import package_2 print(package_2 is package_1.package2) #False 中的所有 对象都与外部模块相同。

这有一些限制,如果您要导入子模块,而不仅仅是package_1.package_2中定义的内容,则会得到package_2/__init__.py。如果你想避免这种情况,你可以:

  • 使用特定的ImportError来导入您需要的所有内容:

    import
  • from package_2 import * from package_2 import submodule1, submodule2, subpackage3 下添加_all.py模块,该模块会导入您想要公开并从中导入的所有内容

当然package_2 - 通常会避免导入,但在这种情况下,它似乎是解决问题的唯一解决方案,不需要破解导入机制。

如果你真的讨厌这个我能想到的另一种方法是使用导入钩子编写一个自定义导入器,但这需要相当多的工作才能使它正确。

此外,由于*现在是它自己的包,您应该考虑弃用旧的导入方式,以便能够在将来的某个版本中删除此“hack”。如果你打算在将来摆脱它,可能花费太多时间编写一个导入钩子是不值得的。


请注意package_2导入:

from

要求您实际提供from package_1.package_2 import module1 模块或子包。

表单的package_1.package_2

import

首先导入from X.Y.Z import something ,然后导入器将在X目录下搜索名为Y.py的文件。然后,它将最终搜索X下的Z.py文件或目录X/Y,如果在导入的X/Y/Z模块中找到something,则会将其放在范围,否则Z是导入的模块。

然而,最后一步,检查something中是否已存在something,仅在<{1}},Z和{{em>} 时执行{1}}已完全导入。在您的用例中:

X

您只是无法Y内简单定义Z