1

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

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 引用它以保持以前的行为。

4

1 回答 1

1

您可以在其下添加一个package_2.py模块,package_1该模块仅包含:

from package_2 import *

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

from __future__ import absolute_import

在文件的顶部,以便具有 python3 的行为。

这种方式package_1.package_2不同于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's 中定义的东西,你会得到一个ImportError. 如果你想避免这种情况,你可以:

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

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

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

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

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


注意from导入:

from package_1.package_2 import module1

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

形式的imports:

from X.Y.Z import something

首先 import ,然后 importer 会在目录下X搜索一个名为的文件。然后它最终会搜索或目录下的文件,如果在导入的模块中找到则简单地放在范围内,否则是导入的模块。Y.pyXZ.pyX/YX/Y/ZsomethingZsomething

然而,最后一步,检查 是否something已经存在Z在所有X,YZ完全导入时才执行。在您的用例中:

from package_1.package_2 import module1

你根本不能简单package_2地在里面定义package_1

于 2014-02-04T21:05:05.457 回答