[英]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
为空我的流程:
C:/test/
添加到sys.path
。import Package
(WORKS)dir(Package)
不列出包内的任何模块。<module 'Package' from C:/test/Package/_init_.py>
__file__
是 Package 下的 init 文件__name__
是Package
__package__
是一个空字符串__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:在moduleA
我from . import moduleB
from . import moduleB
不行,同样的错误
测试 1 - 版本 3:在moduleA
我import 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.moduleB
将Package
作为变量 令人惊讶的是, Package
看起来像一个合适的包,并且包含两个模块。
事实上,在版本 1 和版本 2 中执行任何导入现在都可以工作,因为现在moduleA
和moduleB
是Package
一部分。
问题:
1) 为什么Package
不被识别为包? 是吗? 它不应该包含所有子模块吗?
2) 为什么运行import Package.moduleA
在moduleA
生成Package
?
3) 为什么运行import Package.moduleA
会将moduleA
添加到Package
而它之前没有?
4) 空的__init__.py
文件和非空的__init__.py
文件对此有影响吗?
5) 定义一个包含['moduleA', 'moduleB']
的__all__
变量在这里有什么作用吗?
6) 如何使 init 文件加载两个子模块? 我应该在里面import Package.moduleA
和Package.moduleB
吗?...我不能像import .moduleA as moduleA
或类似的东西那样做吗? (如果Package
的名称发生变化怎么办?)
7) 包变量上的空字符串有影响吗? 如果我们想让它识别自己,我们应该更改它的内容...... __package__
应该与__name__
相同,或者这就是 PEP 所说的。 但是这样做没有用:
if __name__ == "__main__" and __package__ is None:
__package__ = "Package"
这是一个循环依赖问题。 它与此问题非常相似,但不同之处在于您尝试从包中导入模块,而不是从模块中导入类。 在这种情况下,最好的解决方案是重新考虑您的代码,以便不需要循环依赖。 将任何常用函数或类移出包中的第三个模块。
担心__package__
是一个红鲱鱼。 当你的包成为一个合适的包时,python 导入系统会适当地设置它。
问题是moduleA
和moduleB
仅在成功导入后才放入package
。 但是,由于moduleA
和moduleB
都在导入过程中,因此它们在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.