第 7 章 模块、包与导入系统
7.1 模块:一个 .py 文件
任何 .py 文件都是一个模块。把代码按功能拆成模块,是组织代码的第一步。
创建 mymath.py:
在其他文件中导入:
7.2 包:带 __init__.py 的目录
包(package)是模块的目录,用于分层组织:
要点:
Python 3.3+ 支持命名空间包(可无
__init__.py),但常规项目仍建议保留它,可在其中做包级初始化和__all__导出声明;绝对导入(从项目根写全路径)优先;相对导入
from . import text只在包内部使用;目录结构即命名空间,避免单层堆几十个模块。
7.3 __name__ == "__main__":模块既能复用又能直接运行
__name__ 是模块的内置属性:
被导入时:
__name__等于模块名(如"mymath");被直接运行时(
python mymath.py):等于"__main__"。
因此标准写法:
没有这层保护时,直接运行的模块里 print("mymath 模块被加载了") 会在每次被导入时执行——这就是为什么入口代码必须包在 if __name__ == "__main__": 里。
7.4 导入搜索路径
导入时 Python 按以下顺序查找(sys.path 列表):
脚本所在目录(或当前目录);
PYTHONPATH环境变量中的目录;标准库目录;
site-packages(第三方包安装位置)。
同名遮蔽陷阱:如果你给自己的文件起名 random.py、json.py,它会遮蔽标准库,导致诡异报错——别用标准库名命名自己的模块。
7.5 标准库速览(内置电池)
Python 的哲学是 "batteries included",常用标准库:
| 模块 | 用途 | 一行示例 |
|---|---|---|
math | 数学函数 | math.sqrt(2), math.pi |
random | 随机数 | random.randint(1, 6) |
datetime | 日期时间 | datetime.now(), date.today() |
os / os.path | 操作系统接口 | os.listdir(".") |
pathlib | 现代路径操作(推荐) | Path("a/b.txt").read_text() |
sys | 解释器与系统 | sys.argv, sys.path |
json | JSON 编解码 | json.dumps(obj), json.load(f) |
re | 正则表达式 | re.findall(r"\d+", s) |
collections | 增强容器 | Counter, defaultdict, deque |
itertools | 迭代工具 | itertools.chain, product |
functools | 函数工具 | functools.cache, partial |
csv | CSV 读写 | csv.reader(f) |
shutil | 高级文件操作 | shutil.copy(src, dst) |
subprocess | 运行外部命令 | subprocess.run(["ls", "-l"]) |
logging | 日志(别用 print 调试生产代码) | logging.info("...") |
unittest / doctest | 测试 | 见第 10 章 |
两个高频示例
7.6 第三方包管理
实践规范:
虚拟环境 + requirements.txt 锁定依赖(见第 1 章);
大项目可迁移到更现代的工具:Poetry、uv、PDM(自动管理虚拟环境和锁文件);
找包去 https://pypi.org,看质量和维护状态再引入。
7.7 创建可分发的包(概念)
一个可发布的项目通常长这样:
pyproject.toml 是 Python 官方现行标准(取代 setup.py),声明名称、版本、依赖、构建后端。发布到 PyPI 用 python -m build + twine upload。初学阶段了解结构即可。
7.8 本章小结
模块 = 文件,包 = 目录;
import x与from x import y按需选择;入口代码包在
if __name__ == "__main__":里;别用标准库名给文件命名;
标准库先找一遍再装第三方包;
pathlib、collections值得最先掌握。
下一章:异常处理与调试。