强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

11 - 模块与包

第 11 章:模块与包

理解 Python 的模块系统、导入机制和包管理,组织大型项目代码。


11.1 模块基础

11.1.1 什么是模块?

一个 .py 文件就是一个模块。模块可以包含函数、类、变量。

# math_utils.py
"""数学工具模块。"""

PI = 3.14159

def add(a: int, b: int) -> int:
    return a + b

def circle_area(radius: float) -> float:
    return PI * radius ** 2

11.1.2 导入方式

# 导入整个模块
import math_utils
print(math_utils.add(1, 2))

# 导入特定成员
from math_utils import add, PI
print(add(1, 2))

# 别名导入
import math_utils as mu
print(mu.circle_area(5))

# 导入所有(不推荐)
from math_utils import *

11.1.3 模块的 __name__

# math_utils.py
def add(a, b):
    return a + b

if __name__ == "__main__":
    # 只在直接运行时执行
    print(f"2 + 3 = {add(2, 3)}")
$ python math_utils.py   # 输出: 2 + 3 = 5
$ python -c "import math_utils"  # 不输出

11.2 包

11.2.1 包的结构

mypackage/
├── __init__.py        # 包初始化(可以为空)
├── core.py            # 子模块
├── utils.py
└── subpackage/
    ├── __init__.py
    └── helpers.py

11.2.2 __init__.py

# mypackage/__init__.py

# 控制 from mypackage import * 的行为
__all__ = ["core", "utils"]

# 包级别的初始化代码
__version__ = "1.0.0"

# 便捷导入
from .core import important_function
from .utils import helper

11.2.3 使用包

# 方式一:完整路径
from mypackage.core import important_function
from mypackage.subpackage.helpers import helper

# 方式二:通过 __init__.py 暴露的接口
from mypackage import important_function

# 方式三:导入子包
import mypackage.subpackage.helpers

11.3 导入机制

11.3.1 搜索路径

import sys
print(sys.path)
# [
#   '',                      # 当前目录
#   '/usr/lib/python312.zip',
#   '/usr/lib/python3.12',
#   '/usr/lib/python3.12/lib-dynload',
#   '/home/user/.venv/lib/python3.12/site-packages',
# ]
# 动态添加搜索路径
import sys
sys.path.insert(0, "/my/custom/path")
sys.path.append("/another/path")

11.3.2 导入过程

import mymodule

1. 搜索模块(sys.path)
2. 检查 sys.modules 缓存
3. 加载模块代码
4. 执行模块顶层代码
5. 将模块绑定到 sys.modules["mymodule"]
import sys

# 查看已导入的模块
print("json" in sys.modules)  # True(已被标准库预导入)

# 查看模块信息
import json
print(sys.modules["json"])    # <module 'json' from '...'>

11.3.3 相对导入

# mypackage/core.py

# 相对导入(使用 . 或 ..)
from . import utils               # 同包的 utils
from .utils import helper         # 同包的 utils 中的 helper
from .. import other_module       # 上级包的 other_module
from ..subpackage import helpers  # 同级子包

# ⚠️ 相对导入只能在包内部使用,不能在脚本顶层使用

11.3.4 导入的最佳实践

# ✅ 标准库 → 第三方库 → 本地模块(用空行分隔)
import os
import sys
from datetime import datetime

import requests
import numpy as np

from myproject.utils import helper
from myproject.models import User

11.4 高级主题

11.4.1 命名空间包(PEP 420)

# 允许将包分散在多个目录中
# 目录结构 A:
#   mynamespace/package_a/module_a.py
# 目录结构 B:
#   mynamespace/package_b/module_b.py

# 不需要 __init__.py
# 两个目录都加入 sys.path 后,可以同时导入
from mynamespace.package_a import module_a
from mynamespace.package_b import module_b

11.4.2 延迟导入

def process_image(path: str):
    """只在函数调用时才导入(减少启动时间)。"""
    from PIL import Image  # 延迟导入
    img = Image.open(path)
    return img

11.4.3 __all__ 控制导出

# utils.py
__all__ = ["public_function", "PublicClass"]

def public_function():
    pass

def _private_function():
    pass

class PublicClass:
    pass

class _PrivateClass:
    pass
from utils import *  # 只导入 public_function 和 PublicClass

11.4.4 模块级别魔术变量

# mymodule.py
print(__name__)      # "__main__" 或 "mymodule"
print(__file__)      # /path/to/mymodule.py
print(__doc__)       # 模块文档字符串
print(__package__)   # 包名或 None
print(__loader__)    # 模块加载器
print(__spec__)      # 模块规范

11.5 常用标准库模块速查

模块用途
os操作系统接口
sys系统参数和函数
pathlib面向对象的路径操作
jsonJSON 编解码
re正则表达式
datetime日期和时间
collections高级容器
itertools迭代器工具
functools函数工具
typing类型注解
logging日志
unittest单元测试
argparse命令行参数
subprocess子进程管理
threading线程
multiprocessing多进程
asyncio异步 I/O
dataclasses数据类
abc抽象基类
contextlib上下文管理器工具

11.6 注意事项

🔴 注意

  • 循环导入会导致 ImportError,使用延迟导入或重构代码解决
  • from module import * 会污染命名空间,避免使用
  • 相对导入在直接运行脚本时不工作,使用 -m 标志运行
  • 不要在 __init__.py 中放太多逻辑

💡 提示

  • 使用 __all__ 明确导出接口
  • 包内的模块之间使用相对导入
  • 使用 if __name__ == "__main__" 保护脚本入口
  • 大型项目使用 src/ 布局避免导入问题

📌 业务场景

# 项目结构
# myproject/
# ├── __init__.py
# ├── config.py      # 配置
# ├── models/         # 数据模型
# │   ├── __init__.py
# │   ├── user.py
# │   └── order.py
# ├── services/       # 业务逻辑
# │   ├── __init__.py
# │   └── order_service.py
# └── api/            # API 接口
#     ├── __init__.py
#     └── routes.py

# services/order_service.py
from ..models.user import User
from ..models.order import Order
from ..config import settings

class OrderService:
    def create_order(self, user: User, items: list) -> Order:
        ...

11.7 扩展阅读