1. 模块和包是什么? #
- 模块(module) 就是一个
.py 文件`,里面定义函数、类、常量等,可被其他文件 import 复用。
- 包(package) 是带
__init__.py 的目录(业务项目普遍保留该文件),把多个模块组织成树形结构,例如 myapp/models.py、myapp/services/user_service.py。
- 全栈项目靠
import 拆分职责;Django、Flask 等框架的目录本质上就是包。
2. 导入的常用写法 #
import 模块名 引入整个模块,使用时写 模块.成员(如 os.path.join)。
from 模块 import 名字 只引入需要的函数或类,代码更短。
import 长名 as 别名 是社区约定(如 pandas as pd)。避免 from xxx import *:名称冲突难排查、IDE 难补全。
import os
from datetime import datetime
import pandas as pd
| 写法 |
说明 |
import math |
清晰,适合用多个成员 |
from math import sqrt |
只用少数几个时 |
import numpy as np |
长模块名缩短 |
from pkg import * |
不推荐,易冲突、难读 |
3. if __name__ == "__main__" #
- 每个模块都有内置变量
__name__。
- 直接运行该
.py(如 python export_users.py)时,__name__ 为 "__main__"。
- 被其他文件
import 时,__name__ 为模块名(如 scripts.export_users)。
- 把「仅当脚本执行时才跑的代码」放在
if __name__ == "__main__": 里。
- 同一文件既可当库被导入,又可当命令行入口,导入时不会误执行
main()。
def main():
print("export users")
if __name__ == "__main__":
main()
4. 包的结构 #
- 中大型项目按包 → 子包 → 模块分层。
models 放数据模型、views 放接口、services 放业务逻辑。
- 目录树示例如下;导入时从项目根包名写绝对路径,或在包内用相对导入(
. / ..)。
myproject/
├── manage.py # 或 app.py 入口
├── requirements.txt
└── myapp/ # 包
├── __init__.py # 可为空;也可做包级导出
├── models.py
├── views.py
└── services/
├── __init__.py
└── user_service.py
4.1 绝对导入(项目里最常用) #
- 从项目根包起写完整路径,不依赖当前文件所在目录。
- 可读性好、IDE 跳转准确,团队项目首选。
- 运行前需保证项目根在
PYTHONPATH 或已安装为可编辑包(pip install -e .)。
from myapp.models import User
from myapp.services.user_service import create_user
print(User)
print(create_user("John"))
4.2 相对导入(包内部模块之间) #
- 仅在包内部的
.py 中使用:. 表示当前包,.. 表示上级包。
- 适合
views.py 引用同包的 models,路径短。
- 项目根下的入口脚本(如
manage.py、main.py)不能用相对导入,须用绝对导入。
from .models import User
from .services.user_service import create_user
4.3 __init__.py #
__init__.py 标明目录是 Python 包(Python 3.3+ 有无命名空间包,但业务项目仍普遍保留该文件)。
- 可为空;也可在包加载时执行初始化。
- 可通过
from .models import User 统一对外导出,让外部写 from myapp import User。
- 还可定义
__all__ 约束 from myapp import * 导出的名称(仍不推荐 import *)。
from .models import User
5. 模块去哪找? #
- 执行
import foo 时,Python 按 sys.path 列表依次查找 foo.py 或 foo/ 包。
- 常见路径包括:当前工作目录、虚拟环境的
site-packages(第三方库)、标准库目录。
- 出现
ModuleNotFoundError 时,检查模块名是否拼错、项目根是否在路径里、虚拟环境是否激活、pip install 是否已装该包。
- 调试时可
print(sys.path) 查看搜索路径。
import sys
print(sys.path)
6. 项目开发要点 #
- 模块与包决定项目能否协作、能否部署。
- 优先绝对导入(从项目根包写全路径),包内模块可用相对导入。
- 只 import 需要的内容,避免
from xxx import *。
- 导入顺序:标准库 → 第三方 → 本项目(PEP 8)。
- 防循环导入:A 引 B、B 又引 A 会报错;抽公共模块到
utils / common,或延迟 import(函数内 import)。
- 一个 .py 职责单一:
models、views、services 分文件,便于测试和协作。
- 入口与库分离:可执行脚本放
scripts/ 或 manage.py,业务逻辑放在包里被 import。
7. 总结 #
- 本章核心:
.py 是模块,带 __init__.py 的目录是包。
- 用 import 复用代码,项目内优先绝对导入,包内可用相对导入。
- 入口用
if __name__ == "__main__"。
- 下表速查。
| 概念 |
要点 |
| 模块 |
.py 文件 |
| 包 |
目录 + __init__.py |
| 绝对导入 |
from myapp.models import User |
| 相对导入 |
from .models import User(仅包内) |
| 入口 |
if __name__ == "__main__": |