# Python开发事实规范:从虚拟环境到工程实践的标准清单
Python开发事实规范:从虚拟环境到工程实践的标准清单
文档定位:总结Python开发中已形成事实规范的常识和最佳实践,帮助开发者建立标准化的开发流程
生成时间:2025-01-XX
相关文档:
目录
1. 虚拟环境规范
1.1 为什么需要虚拟环境
核心问题:全局包污染
- Python默认安装到系统目录(
/usr/lib/python3.x/site-packages/) - 所有项目共享同一个包空间
- 不同项目可能依赖同一包的不同版本,产生冲突
虚拟环境的作用:
- 隔离依赖:每个项目独立的包目录
- 版本隔离:同一包可安装不同版本
- 环境可复现:通过
requirements.txt或pyproject.toml锁定版本
1.2 使用规范
传统方式:
python -m venv .venv
source .venv/bin/activate # Linux/Mac
# 或 .venv\Scripts\activate # Windows
pip install -r requirements.txt
现代工具(UV):
uv sync # 自动创建虚拟环境 + 安装依赖
uv run script.py # 自动在虚拟环境中运行
1.3 事实规范
| 场景 | 是否需要虚拟环境 |
|---|---|
| 学习Python | ✅ 建议使用(养成好习惯) |
| 开发项目 | ✅ 强烈推荐(几乎必需) |
| 生产部署 | ✅ 必须使用 |
| 一次性脚本 | ⚠️ 可以不用 |
| 系统工具 | ❌ 通常不用(全局安装) |
总结:
- 技术上:不是强制的,可以直接用系统Python
- 实践中:强烈推荐,接近必需
- 趋势上:现代工具(如UV)正在让虚拟环境成为默认行为
2. 项目结构规范
2.1 标准项目布局
my-project/
├── src/ # 源代码目录(推荐布局)
│ └── my_project/
│ └── __init__.py
├── tests/ # 测试目录
├── pyproject.toml # 现代项目配置(已替代setup.py)
├── README.md # 项目说明
├── .gitignore # Git忽略文件
└── .venv/ # 虚拟环境(不提交到Git)
2.2 关键文件说明
__init__.py:
- 使目录成为Python包
- Python 3.3+支持namespace packages(可省略),但显式声明仍是推荐做法
src/ 布局:
- 避免导入冲突
- 推荐用于库项目
- 应用项目可直接使用根目录
tests/ 目录:
- 测试与代码分离
- 可使用
pytest自动发现测试
2.3 事实规范
- ✅ 使用
src/布局(库项目) - ✅ 独立的
tests/目录 - ✅
__init__.py显式声明包 - ✅
README.md项目说明 - ✅
.gitignore忽略缓存和虚拟环境
3. 依赖管理规范
3.1 从 requirements.txt 到 pyproject.toml
传统方式(requirements.txt):
requests>=2.25.0
click>=8.0.0
现代标准(pyproject.toml):
[project]
name = "my-project"
version = "0.1.0"
dependencies = [
"requests>=2.25.0",
"click>=8.0.0"
]
requires-python = ">=3.8"
[project.optional-dependencies]
dev = [
"pytest>=6.0",
"black>=21.0",
"ruff>=0.0.200"
]
test = ["pytest", "pytest-cov"]
docs = ["sphinx", "sphinx-rtd-theme"]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
3.2 锁文件管理
现代工具锁文件:
uv.lock(UV工具)poetry.lock(Poetry工具)Pipfile.lock(Pipenv工具)
事实规范:
- ✅ 使用
pyproject.toml(PEP 518/621标准) - ✅ 提交锁文件到版本控制
- ✅ 依赖分组(dev/test/docs)
- ✅ 明确
requires-python版本要求 - ❌ 不再推荐
setup.py(除非打包发布)
4. 代码风格规范
4.1 PEP 8 核心规则
缩进:
- 4个空格(不使用Tab)
- 行长度:79/88/100字符(项目统一)
命名规范:
snake_case:函数、变量名PascalCase:类名UPPER_CASE:常量_single_leading_underscore:内部使用__double_leading_underscore:名称修饰(避免使用)
4.2 工具链
格式化工具:
black . # 自动格式化(事实标准)
ruff format . # 更快的black替代
Linting工具:
ruff check . # 超快的linter(替代flake8)
pylint . # 更严格的检查(可选)
事实规范:
- ✅ 使用
black或ruff format自动格式化 - ✅ 使用
ruff进行代码检查 - ✅ 项目统一代码风格配置
- ✅ CI/CD中集成格式化和检查
5. 类型注解规范
5.1 PEP 484/526 类型提示
函数类型注解:
def process_data(data: dict[str, int]) -> list[str]:
"""处理数据并返回字符串列表"""
return [str(v) for v in data.values()]
变量类型注解:
count: int = 0
items: list[str] = []
user: dict[str, Any] = {}
类型检查工具:
mypy . # 静态类型检查
5.2 事实规范
- ✅ 公共API必须有类型注解
- ✅ 使用
mypy进行类型检查 - ✅ Python 3.9+ 使用内置类型(
list[str]而非List[str]) - ✅ 复杂类型使用
typing模块 - ✅ 可选类型使用
Optional[T]或T | None(Python 3.10+)
6. 测试规范
6.1 pytest 是事实标准
测试文件结构:
# tests/test_example.py
import pytest
from my_project import add
def test_add_positive_numbers():
assert add(1, 2) == 3
def test_add_negative_numbers():
assert add(-1, -2) == -3
@pytest.fixture
def sample_data():
return {"key": "value"}
def test_with_fixture(sample_data):
assert "key" in sample_data
测试运行:
pytest # 运行所有测试
pytest tests/ # 运行指定目录
pytest -v # 详细输出
pytest --cov=. # 覆盖率报告
6.2 事实规范
- ✅ 使用
pytest(而非unittest) - ✅ 测试文件命名:
test_*.py - ✅ 测试函数命名:
test_* - ✅ 使用
pytest-cov生成覆盖率报告 - ✅ 测试覆盖率目标:80%+(根据项目要求)
- ✅ 集成测试和单元测试分离
7. 文档规范
7.1 Docstring 标准
Google风格(推荐):
def function(param: str, optional: int = 10) -> int:
"""简短描述。
详细描述(可选),可以多行说明函数的作用、
参数含义、返回值等。
Args:
param: 参数说明
optional: 可选参数说明,默认值为10
Returns:
返回值说明
Raises:
ValueError: 当参数无效时抛出
Example:
>>> function("test", 20)
20
"""
pass
NumPy风格:
def function(param, optional=10):
"""
简短描述。
Parameters
----------
param : str
参数说明
optional : int, optional
可选参数说明,默认值为10
Returns
-------
int
返回值说明
"""
pass
7.2 文档生成
Sphinx文档生成:
sphinx-build -b html docs/ docs/_build/
7.3 事实规范
- ✅ 使用 Google/NumPy/Sphinx 风格(项目统一)
- ✅ 公共API必须有docstring
- ✅ 使用
sphinx生成HTML文档 - ✅ README.md包含项目概述和使用说明
- ✅ CHANGELOG.md记录版本变更
8. 版本管理规范
8.1 语义化版本(SemVer)
版本格式:MAJOR.MINOR.PATCH
[project]
version = "1.2.3" # 主版本.次版本.修订版本
版本号规则:
- MAJOR:不兼容的API修改
- MINOR:向下兼容的功能性新增
- PATCH:向下兼容的问题修正
8.2 Python版本要求
[project]
requires-python = ">=3.8" # 明确最低Python版本
8.3 事实规范
- ✅ 遵循 SemVer 语义化版本
- ✅ 在
pyproject.toml中声明版本 - ✅ 明确
requires-python最低版本 - ✅ 维护 CHANGELOG.md 记录版本变更
9. Git规范
9.1 .gitignore 标准
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# 虚拟环境
.venv/
venv/
ENV/
env/
.ENV
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
# 测试和覆盖率
.pytest_cache/
.mypy_cache/
.coverage
htmlcov/
.tox/
# 环境变量
.env
.env.local
# 日志
*.log
9.2 提交规范
提交信息格式(Conventional Commits):
feat: 添加新功能
fix: 修复bug
docs: 文档更新
style: 代码格式调整
refactor: 代码重构
test: 测试相关
chore: 构建/工具相关
9.3 事实规范
- ✅ 忽略
__pycache__/、.venv/、.pytest_cache/ - ✅ 提交
pyproject.toml和锁文件 - ✅ 不提交虚拟环境和缓存文件
- ✅ 使用有意义的提交信息
- ✅ 遵循 Conventional Commits 规范
10. 导入规范
10.1 PEP 8 导入顺序
# 1. 标准库导入
import os
import sys
from typing import Optional, List
# 2. 第三方库导入
import requests
import numpy as np
from django import forms
# 3. 本地应用/库导入
from my_project import utils
from my_project.models import User
导入规则:
- 每组导入之间空一行
- 每组内按字母顺序排序
- 使用
isort自动排序
10.2 导入工具
isort . # 自动排序导入
isort --check-only . # 仅检查不修改
10.3 事实规范
- ✅ 按标准库 → 第三方 → 本地顺序
- ✅ 使用
isort自动排序导入 - ✅ 避免
from module import * - ✅ 使用绝对导入(Python 3+)
- ✅ 长导入使用括号换行
11. 异常处理规范
11.1 异常处理最佳实践
好的做法:
import logging
logger = logging.getLogger(__name__)
try:
result = process_data(data)
except ValueError as e:
logger.error(f"数据验证失败: {e}")
raise # 重新抛出或处理
except FileNotFoundError as e:
logger.error(f"文件未找到: {e}")
return None # 或提供默认值
except Exception as e:
logger.exception("未预期的错误")
raise
避免的做法:
# ❌ 捕获所有异常
try:
process()
except:
pass # 静默忽略
# ❌ 过于宽泛的异常
try:
process()
except Exception: # 应该捕获具体异常
pass
11.2 事实规范
- ✅ 捕获具体异常(避免裸
except) - ✅ 记录异常信息(使用logging)
- ✅ 不要静默忽略异常
- ✅ 重新抛出或适当处理
- ✅ 使用
logger.exception()记录完整堆栈
12. 环境变量管理
12.1 .env 文件使用
环境变量文件:
# .env
DATABASE_URL=postgresql://user:pass@localhost/db
API_KEY=secret_key_here
DEBUG=True
加载环境变量:
# 使用 python-dotenv
from dotenv import load_dotenv
import os
load_dotenv() # 加载.env文件
database_url = os.getenv("DATABASE_URL")
api_key = os.getenv("API_KEY")
环境变量模板:
# .env.example(提交到Git)
DATABASE_URL=postgresql://user:pass@localhost/db
API_KEY=your_api_key_here
DEBUG=True
12.2 事实规范
- ✅ 使用
python-dotenv加载环境变量 - ✅
.env文件加入.gitignore - ✅ 提供
.env.example模板文件 - ✅ 敏感信息使用环境变量(不硬编码)
- ✅ 使用
pydantic-settings进行配置管理(可选)
13. 日志规范
13.1 logging 模块使用
基础配置:
import logging
# 模块级logger
logger = logging.getLogger(__name__)
def process():
logger.info("开始处理")
try:
result = do_work()
logger.debug(f"处理结果: {result}")
return result
except Exception as e:
logger.error(f"处理失败: {e}", exc_info=True)
raise
日志配置:
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('app.log'),
logging.StreamHandler()
]
)
13.2 事实规范
- ✅ 使用
logging模块(不用print) - ✅ 使用模块级 logger(
__name__) - ✅ 配置日志级别和格式
- ✅ 生产环境使用适当的日志级别
- ✅ 敏感信息不记录到日志
- ✅ 使用结构化日志(JSON格式,可选)
事实规范快速参考表
| 规范类别 | 事实标准 | 工具/格式 | 必需程度 |
|---|---|---|---|
| 虚拟环境 | venv/uv | .venv/ |
⭐⭐⭐⭐⭐ |
| 项目结构 | src布局 + tests目录 | __init__.py |
⭐⭐⭐⭐ |
| 依赖管理 | pyproject.toml | PEP 518/621 | ⭐⭐⭐⭐⭐ |
| 代码风格 | PEP 8 | black / ruff |
⭐⭐⭐⭐ |
| 类型检查 | 类型注解 | mypy |
⭐⭐⭐ |
| 测试框架 | pytest | pytest-cov |
⭐⭐⭐⭐ |
| 文档 | Docstring | Google/NumPy风格 | ⭐⭐⭐ |
| 版本管理 | SemVer | pyproject.toml |
⭐⭐⭐ |
| Git | .gitignore标准 | 忽略缓存/虚拟环境 | ⭐⭐⭐⭐⭐ |
| 导入 | PEP 8顺序 | isort |
⭐⭐⭐ |
| 异常 | 具体异常捕获 | logging记录 | ⭐⭐⭐⭐ |
| 环境变量 | .env文件 | python-dotenv |
⭐⭐⭐⭐ |
| 日志 | logging模块 | 模块级logger | ⭐⭐⭐⭐ |
总结
这些规范在Python社区中已经形成事实标准,遵循它们能够:
- 提高代码质量:统一的风格和规范
- 便于团队协作:标准化的项目结构
- 降低维护成本:清晰的依赖和文档
- 提升开发效率:自动化工具支持
建议:
- 新项目从一开始就遵循这些规范
- 老项目逐步迁移到现代标准
- 使用工具自动化检查和格式化
- 在CI/CD中集成规范检查
相关资源
- PEP 8 -- Style Guide for Python Code
- PEP 518 -- Specifying Build System Dependencies
- PEP 621 -- Project metadata
- Python Packaging User Guide
- pytest Documentation
- mypy Documentation
文档版本:v1.0
最后更新:2025-01-XX

浙公网安备 33010602011771号