模块是单个.py文件,为最小可导入单位;包是含__init__.py的目录,用于组织多个模块并支持嵌套。import机制包含查找、加载、缓存、绑定四步,首次导入执行顶层代码并缓存于sys.modules,重复导入直接返回缓存对象。
python 中的模块(module)和包(package)本质都是组织代码的方式,但层级与用途不同:模块是单个 .py 文件,是可导入的最小单位;包是包含 __init__.py(可以为空)的目录,用于逻辑分组多个模块,支持嵌套结构。import 机制则是一套运行时查找、加载、缓存并绑定名称的完整流程,不是简单的“复制粘贴”。
模块:单文件即模块,直接可 import
一个 hello.py 就是一个模块。只要它在 Python 的模块搜索路径(sys.path)中,就能被直接导入:
- import hello → 导入后通过 hello.func() 访问
- from hello import greet → 直接使用 greet()
- 模块首次导入时会被编译为 .pyc 缓存在 __pycache__ 中,后续加速加载
包:带 __init__.py 的目录,支持层级导入
包的本质是一个有组织的模块集合。例如:
mylib/
├── __init__.py
├── utils.py
└── data/
├── __init__.py
└── loader.py
- import mylib.utils → 需要 mylib/__init__.py 存在(哪怕为空)
- from mylib.data import loader → mylib/data/__init__.py 决定该子包是否可被导入
- __init__.py 可以定义 __all__ 控制 from mylib import * 暴露的内容
- 包内模块可通过相对导入(如 from . import utils 或 from ..other import helper),但仅限于模块被作为包的一部分执行时(不能直接运行 .py 文件)
import 是如何工作的?四步核心机制
执行 import x 时,CPython 实际完成以下动作:
- 查找:按 sys.path 顺序搜索 x.py(模块)或 x/__init__.py(包)
- 加载:若未加载过,读取源码、编译为字节码、执行顶层语句(__init__.py 里的代码也会在此刻运行)
- 缓存:模块对象存入 sys.modules 字典,键为模块全名(如 'mylib.utils')。重复 import 直接返回缓存对象,不重执行
- 绑定:在当前命名空间插入名称(如 import x → 绑定 x;from x import y → 绑定 y)
常见陷阱与实用建议
- 修改已导入模块的源码后,import 不会自动重载 —— 需用 importlib.reload(m)(注意:仅刷新模块对象,不会更新已引用其属性的其他变量)
- 循环导入 往往因顶层执行依赖引发,可将 import 移到函数内部延迟加载来缓解
- 避免在 __init__.py 中做耗时操作,它会在每次导入包或其子模块时执行
- 推荐显式导入:用 from pkg.sub import func 而非 import pkg 后写 pkg.sub.func,语义更清晰、性能略优










