我一直在阅读很多帖子,与这个问题相关的PEP文章大约有4个,但是没有一个在某些方面给出了明确的想法,我仍然无法做到相对进口。
事实上,我的主包的内容根本没有列出。
REEDITION。我修改了所有帖子,它太复杂了,问题也很多。
在C:/test/
我有这个包:
Package/ (FOLDER 2)
__init__.py
moduleA.py
moduleB.py
moduleA
导入moduleB
,反之亦然。__init__.py
为空我的流程:
C:/test/
添加到sys.path
。import Package
(WORKS)dir(Package)
不列出Package中的任何模块。 <module ‘Package’ from C:/test/Package/_init_.py>
__file__
是Package __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
不起作用,同样的错误
测试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
内运行Package
生成moduleA
?
3)为什么运行import Package.moduleA
会将moduleA
添加到Package
并且之前没有?
4)空__init__.py
个文件和NON空__init__.py
文件是否会对此产生影响?
5)定义包含__all__
的{{1}}变量是否会在此处执行任何操作?
6)如何使init文件加载两个子模块?我应该在['moduleA', 'moduleB']
和import Package.moduleA
里面做什么?...我能不能像Package.moduleB
或类似的那样做? (如果import .moduleA as moduleA
的名称发生变化,该怎么办?)
7)包变量上的空字符串是否会影响?如果我们希望它能够识别自己,我们应该更改它的内容...... Package
应该与__package__
相同,或者是PEP所说的内容。但这样做并不奏效:
__name__
答案 0 :(得分:1)
这是一个循环依赖问题。它与此question非常相似,但不同之处在于您尝试从包中导入模块,而不是从模块中导入类。在这种情况下,最好的解决方案是重新考虑您的代码,以便不需要循环依赖。将任何常用函数或类移出到包中的第三个模块。
担心__package__
是一只红鲱鱼。当您的包成为正确的包时,python导入系统将适当地设置它。
问题是moduleA
和moduleB
只有在成功导入后才会放在package
中。但是,由于moduleA
和moduleB
都处于导入状态,因此无法在package
中看到对方。当您绕过相对导入机制时,绝对导入部分解决了问题。但是,如果您的模块在初始化期间需要彼此的部分,则程序将失败。
如果删除var = ...
行,则以下代码可以使用。
package.moduleA
import package.moduleB
def func():
return 1
package.moduleB
import package.moduleA
var = package.moduleA.func() # error, can't find moduleA
package.moduleA
from . import moduleB
def depends_on_y():
return moduleB.y()
def x():
return "x"
package.moduleB
from . import moduleA
def depends_on_x():
return moduleA.x()
def y():
return "y"
package.common
def x():
return "x"
def y():
return "y"
package.moduleA
from .common import y
def depends_on_y():
return y()
package.moduleB
from .common import x
def depends_on_x():
return x()
答案 1 :(得分:0)
这是一个Python错误,存在于3.5之前的Python版本中。请参阅issue 992389讨论的内容(多年)和issue 17636,其中解决了问题的常见情况。
在Python 3.5中进行修复后,在from . import moduleA
包中的模块中显式相对导入(Package
)会在放弃sys.modules
之前检查Package.moduleA
,然后放弃moduleA
尚未提供Package
。由于模块对象在开始加载之前已添加到sys.modules
,但在加载完成之前未添加到Package.__dict__
,这通常可以解决问题。
使用from package import *
进行循环导入仍然存在问题,但在issue 23447(我为其提供了补丁)中,确定修复那个更加模糊的角落案例并不值得额外的代码复杂性。
循环进口通常是设计糟糕的表现。您可能要么将依赖于彼此的代码位重构为两个其他模块导入的单个实用程序模块,要么将两个单独的模块组合成一个单独的模块。