python - 填充的 __init__ 似乎阻止访问同一包中的模块
问题描述
在一个项目中,一个模块moduleA
需要访问moduleB
同一子包中的模块packageA
(在 package 中project
)。此访问失败,当__init__.py
子包的子包packageA
填充了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
是空的,但子包__init__.py
是填充的?
解决方案
这种行为实际上不能用预期的后端机制的任何特性来描述:该行为与任何文档都不匹配,例如PEP 0221。因此,该import .. as ..
语句是无效的。这个错误似乎已经用Python 3.7 修复了(我一直在运行 3.69)
推荐阅读
- python - ImportError:在 conda 安装后没有名为 scipy.spatial 的模块
- django - Django 无法进行迁移
- sql - 如何对新价格和旧价格进行嵌套查询
- sql - Laravel 迁移 Darabase 时出错:BadMethodCallException 方法 \Blueprint::url 不存在
- wpf - WPF MVVM - 如何将服务注入 ViewModel
- scala - 如何在 Scala 中使用反射。我正在尝试使用 getDeclaredMethod()
- swiftui - 我在 SwiftUI 中的设计中的堆栈视图未正确显示
- d3.js - 将文本添加到创建的 D3js 形状(矩形和三角形符号)
- javascript - 如何从承诺中获得结果价值?
- ios - 如何在文件管理器中快速读取 json 文件?