Python 模块、包与导入
模块是可导入单元,包组织模块层级;区分 import/from 的名字绑定、模块缓存和绝对/相对导入。
#concept
#growing
#dev
#python
#python
[!info] related notes
Python 模块、包与导入
这个概念为什么出现
项目一大,单文件不可维持。模块/包划分边界,import 决定依赖是否显式、是否循环、测试能否导入。
[!abstract] 一句话理解 模块是可导入的代码单元,包是模块的层级命名空间;import 执行模块并缓存,优先绝对导入与清晰包边界。
最小可运行示例
先把示例放进业务场景,再看代码:
场景:计价辅助函数使用 math 模块及导入别名
# 以下为可运行单文件演示 import 绑定(真实项目拆多文件)。
# import_binding_demo.py
# 业务意图:展示 import / from-import 绑定差异。
# 教学点:
# - import 绑定模块对象;
# - from 绑定模块属性当前引用的对象,不复制它;
# - 模块缓存直觉。
import math as m
from math import ceil
def quote(price: float) -> int:
return m.ceil(price)
def main() -> None:
print(quote(10.2))
print("math name:", m.__name__)
print("same function?", ceil is m.ceil)
if __name__ == "__main__":
main()
建议运行:
python import_binding_demo.py
期望输出:
11
math name: math
same function? True
结合场景再看三个关注点
- import math as m 在当前模块绑定模块对象;from math import ceil 绑定其当前 ceil 对象。
- from math import ceil 绑定当前函数对象;若模块稍后重绑该属性,本地 ceil 不会自动换绑。若导入的是可变对象,双方仍可观察其原地修改。
- 循环导入靠边界重划与延迟 import 处理。
核心概念与准确模型
| 概念 | 含义 |
|---|---|
| 模块 | 通常一个 .py |
| 包 | 有 __path__ 的模块,可组织子模块;普通包有 __init__.py,namespace package 可没有 |
sys.modules | 导入缓存 |
| 绝对导入 | from billing.pricing import quote |
| 相对导入 | from .pricing import quote(仅包内) |
边界情况与反直觉行为
- 脚本目录 vs 已安装包 同名遮蔽。
- 相对导入不能在脚本顶层随意跑。
from x import *污染命名空间。
常见误区
[!warning] 常见误区:用 sys.path.append 当工程方案 错误理解:临时路径即架构。
正确模型:可编辑安装/正确包布局。
工程实践
- 包对外导出在
__init__克制 - 公共 API 绝对导入
- 应用入口
python -m
本节总结
导入是依赖显式化工具。包边界清晰比“能 import 就行”更重要。
自测题
- 再次 import 同一模块会重新执行吗?
- 为何推荐绝对导入?
参考答案
- 通常不会,命中
sys.modules。 - 绝对导入明确从顶层包出发,便于读依赖;包内相对导入也有合法用途,二者都不能保证任意重构无需修改。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| Modules tutorial | 教程 | 模块与包 |
| Import system | 规范 | 导入 |