繁体   English   中英

Python 导入失败。 相对导入、包识别、__init__.py、__package__、__all__

[英]Python Imports failing. Relative imports, package recognition, __init__.py , __package__, __all__

我一直在阅读很多线程,与此问题相关的 PEP 文章,大约有 4 篇,但没有一篇文章在某些方面给出了明确的想法,我仍然无法进行相对导入。

事实上,我的主包的内容根本没有列出。

再版。 我修改了所有帖子,它太复杂了,问题很多。

C:/test/我有这个包:

Package/ (FOLDER 2)
    __init__.py
    moduleA.py
    moduleB.py
  • moduleA导入moduleB ,反之亦然。
  • __init__.py为空

我的流程:

  1. 我将C:/test/添加到sys.path
  2. import Package (WORKS)
  3. dir(Package)不列出包内的任何模块。
  4. 包是: <module 'Package' from C:/test/Package/_init_.py>
  5. __file__是 Package 下的 init 文件
  6. __name__Package
  7. __package__是一个空字符串
  8. __path__C:/test/Package

测试 1 - 版本 1:在moduleA我有from Package import moduleB

我明白了:

>>> import Package.moduleA
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:/test\Package\moduleA.py", line
    from Package import moduleB
  File "C:/test\Package\moduleB.py", line
    from Package import moduleA
ImportError: cannot import name moduleA

它不起作用,因为moduleA不是Package一部分。 所以Package不被识别为包?


测试 1 - 版本 2:在moduleAfrom . import moduleB from . import moduleB

不行,同样的错误


测试 1 - 版本 3:在moduleAimport Package.moduleB

有用。

之后,运行:

>>> dir(Package.moduleB)
['Package', '__builtins__', '__doc__', '__file__', '__name__', '__package__']
>>> Package.moduleB.Package
<module 'Package' from 'C:/prueba\Package\__init__.py'>
>>> dir(Package)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', 'moduleA', 'moduleB']

所以现在, Package.moduleBPackage作为变量 令人惊讶的是, Package看起来像一个合适的包,并且包含两个模块。

事实上,在版本 1 和版本 2 中执行任何导入现在都可以工作,因为现在moduleAmoduleBPackage一部分。


问题:

1) 为什么Package不被识别为包? 是吗? 它不应该包含所有子模块吗?

2) 为什么运行import Package.moduleAmoduleA生成Package

3) 为什么运行import Package.moduleA会将moduleA添加到Package而它之前没有?

4) 空的__init__.py文件和非空的__init__.py文件对此有影响吗?

5) 定义一个包含['moduleA', 'moduleB']__all__变量在这里有什么作用吗?

6) 如何使 init 文件加载两个子模块? 我应该在里面import Package.moduleAPackage.moduleB吗?...我不能像import .moduleA as moduleA或类似的东西那样做吗? (如果Package的名称发生变化怎么办?)

7) 包变量上的空字符串有影响吗? 如果我们想让它识别自己,我们应该更改它的内容...... __package__应该与__name__相同,或者这就是 PEP 所说的。 但是这样做没有用:

if __name__ == "__main__" and __package__ is None:
    __package__ = "Package"

这是一个循环依赖问题。 它与此问题非常相似,但不同之处在于您尝试从包中导入模块,而不是从模块中导入类。 在这种情况下,最好的解决方案是重新考虑您的代码,以便不需要循环依赖。 将任何常用函数或类移出包中的第三个模块。

担心__package__是一个红鲱鱼。 当你的包成为一个合适的包时,python 导入系统会适当地设置它。

问题是moduleAmoduleB仅在成功导入后才放入package 但是,由于moduleAmoduleB都在导入过程中,因此它们在package无法看到彼此。 当您绕过相对导入机制时,绝对导入部分解决了问题。 但是,如果您的模块在初始化期间需要彼此的一部分,则程序将失败。

如果var = ...行被删除,以下代码将起作用。

包.moduleA

import package.moduleB
def func():
    return 1

包.moduleB

import package.moduleA
var = package.moduleA.func() # error, can't find moduleA

破损包裹示例

包.moduleA

from . import moduleB
def depends_on_y():
    return moduleB.y()
def x():
    return "x"

包.moduleB

from . import moduleA
def depends_on_x():
    return moduleA.x()
def y():
    return "y"

将公共部分提取到包中的单独模块中的示例

包.common

def x():
    return "x"
def y():
    return "y"

包.moduleA

from .common import y
def depends_on_y():
    return y()

包.moduleB

from .common import x
def depends_on_x():
    return x()

这是 Python 3.5 之前版本中存在的 Python 错误。 请参阅问题 992389 (多年)和问题 17636 ,其中修复了该问题的常见情况。

在 Python 3.5 中修复之后,一个显式的相对导入,如from . import moduleA 从包内的模块中from . import moduleA Package将在sys.modules检入Package.moduleA ,如果moduleA尚不存在于Package ,则moduleA 由于模块对象在开始加载之前添加到sys.modules ,但直到加载完成后才添加到Package.__dict__ ,因此这通常可以解决问题。

使用from package import *进行循环导入仍然可能存在问题,但在issue 23447 (我为其贡献了补丁)中,决定修复更模糊的极端情况不值得额外的代码复杂性。

圆形进口通常是不良设计的标志。 您可能应该将相互依赖的代码部分重构为一个由其他模块导入的单个实用程序模块,或者您应该将两个单独的模块合并为一个。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM