【发布时间】:2020-06-16 05:17:51
【问题描述】:
在一个项目中,一个模块moduleA 需要访问同一子包packageA(在包project 中)中的模块moduleB。
当子包packageA的__init__.py被import .. as ..语句填充,而包项目的__init__py为空时,访问失败。
为什么填充的__init__.py(看似)阻止来自此(相同包)模块的访问 - 而 PyCharm 似乎仍然从自动完成和突出显示的角度接受它?
抛出的AttributeError 表明import .. as .. 语句使解释器相信子包是一个属性,而不是一个包——尽管存在一个__init__.py。
文件结构
├── ProjectA
│ ├── src
│ │ ├── project
│ │ │ ├── __init__.py
│ │ │ ├── packageA
│ │ │ │ ├── __init__.py
│ │ │ │ ├── moduleA.py
│ │ │ │ ├── moduleB.py
代码示例 1
# ProjectA / src / project / __init__.py
(empty)
# packageA / __init__.py
(empty)
# packageA / moduleA.py
import project.packageA.moduleB as dummy
class A:
pass
class B:
pass
# packageA / moduleB.py
def method():
pass
代码执行1
# jupyter stated in 'C:\\Users\\username\\Desktop\\devenv\\'
# notebook located in 'C:\\Users\\username\\Desktop\\devenv\\dev\\'
import sys
sys.path
# output:
# ['C:\\src\\ProjectA',
# 'C:\\src\\ProjectA\\src',
# 'C:\\Users\\username\\Desktop\\devenv\\dev',
# 'C:\\ProgramData\\Anaconda3\\envs\\myenv\\python36.zip',
# 'C:\\ProgramData\\Anaconda3\\envs\\myenv\\DLLs',
# 'C:\\ProgramData\\Anaconda3\\envs\\myenv\\lib',
# 'C:\\ProgramData\\Anaconda3\\envs\\myenv',
# '',
# 'C:\\ProgramData\\Anaconda3\\envs\\myenv\\lib\\site-packages',
# 'C:\\ProgramData\\Anaconda3\\envs\\myenv\\lib\\site-packages\\win32',
# 'C:\\ProgramData\\Anaconda3\\envs\\myenv\\lib\\site-packages\\win32\\lib',
# 'C:\\ProgramData\\Anaconda3\\envs\\myenv\\lib\\site-packages\\Pythonwin',
# 'C:\\ProgramData\\Anaconda3\\envs\\myenv\\lib\\site-packages\\IPython\\extensions',
# 'C:\\Users\\username\\.ipython']
from project.packageA.moduleA import A, B
# no error(s)
代码示例 2
packageA / __init__.py的第一个替代填充
# packageA / __init__.py
from .moduleA import A, B
import .moduleB as dummy
packageA / __init__.py的第二个替代填充
# packageA / __init__.py
from project.packageA.moduleA import A, B
import project.packageA.moduleB as dummy
代码执行2
from project.packageA.moduleA import A, B
AttributeError Traceback (most recent call last)
<ipython-input-1-61a791f79421> in <module>
----> 1 import project.packageA.moduleA.moduleB
C:\src\ProjectA\src\project\packageA\__init__.py in <module>
----> 1 from .moduleA import A, B
2 from .moduleB import *
C:\src\ProjectA\src\project\packageA\moduleA.py in <module>
---> 1 import project.packageA.moduleB as dummy
2
3 class A:
AttributeError: module 'project' has no attribute 'packageA'
解决方案
我在Stack Overflow: Imports in __init__.py and import as statement找到了解决方案
将packageA / __init__.py 中的导入从import .. as 更改为from xx import .. as 成功了:
# packageA / __init__.py
from project.packageA.moduleA import A, B
from project.packageA import moduleB as dummy
谁能帮我理解,为什么 import xx as 和 from xx import xx as 工作方式不同,当涉及到子包时——特别是在这种情况下,包的 __init__.py 为空,但子包的 @ 987654349@满了吗?
【问题讨论】:
标签: python import module package init