010-开发依赖与生产依赖
学习目标
通过本章节的学习,您将掌握:
- Poetry依赖组的概念和使用方法
- 开发依赖与生产依赖的分离策略
- 不同环境下的依赖管理最佳实践
- 可选依赖和额外功能的配置
- 依赖组的高级管理技巧
依赖组概念
什么是依赖组
Poetry使用依赖组(Dependency Groups)来组织和管理不同用途的依赖包:
- 主依赖:应用运行时必需的依赖
- 开发依赖:开发过程中需要的工具和库
- 测试依赖:运行测试时需要的依赖
- 文档依赖:生成文档时需要的依赖
- 自定义组:根据项目需要定义的特殊依赖组
依赖组的优势
# pyproject.toml
[tool.poetry.dependencies]
python = "^3.8"
requests = "^2.28.0"
fastapi = "^0.85.0"
[tool.poetry.group.dev.dependencies]
pytest = "^7.1.0"
black = "^22.0.0"
isort = "^5.10.0"
[tool.poetry.group.test.dependencies]
pytest-cov = "^4.0.0"
pytest-mock = "^3.8.0"
[tool.poetry.group.docs.dependencies]
sphinx = "^5.0.0"
sphinx-rtd-theme = "^1.0.0"
主依赖管理
生产环境依赖
# 添加生产依赖
poetry add requests
poetry add fastapi
poetry add sqlalchemy
# 添加带版本约束的依赖
poetry add "django>=4.0,<5.0"
poetry add "numpy^1.21.0"
# 添加可选依赖
poetry add psycopg2-binary --optional
# 查看主依赖
poetry show --only=main
主依赖配置示例
[tool.poetry.dependencies]
python = "^3.8"
# Web框架
fastapi = "^0.85.0"
uvicorn = {extras = ["standard"], version = "^0.18.0"}
# 数据库
sqlalchemy = "^1.4.0"
alembic = "^1.8.0"
psycopg2-binary = {version = "^2.9.0", optional = true}
# 数据处理
pydantic = {extras = ["email"], version = "^1.10.0"}
python-multipart = "^0.0.5"
# 工具库
requests = "^2.28.0"
python-jose = {extras = ["cryptography"], version = "^3.3.0"}
passlib = {extras = ["bcrypt"], version = "^1.7.0"}
# 配置管理
python-dotenv = "^0.20.0"
开发依赖管理
开发工具依赖
# 添加开发依赖
poetry add --group dev pytest
poetry add --group dev black
poetry add --group dev isort
poetry add --group dev flake8
poetry add --group dev mypy
# 批量添加开发依赖
poetry add --group dev pytest black isort flake8 mypy pre-commit
# 查看开发依赖
poetry show --only=dev
开发依赖配置
[tool.poetry.group.dev]
optional = false
[tool.poetry.group.dev.dependencies]
# 测试工具
pytest = "^7.1.0"
pytest-asyncio = "^0.19.0"
pytest-cov = "^4.0.0"
pytest-mock = "^3.8.0"
httpx = "^0.23.0"
# 代码格式化
black = "^22.0.0"
isort = "^5.10.0"
autoflake = "^1.4.0"
# 代码检查
flake8 = "^5.0.0"
mypy = "^0.991"
bandit = "^1.7.0"
safety = "^2.2.0"
# 开发工具
pre-commit = "^2.20.0"
ipython = "^8.5.0"
jupyter = "^1.0.0"
# 调试工具
pdb++ = "^0.10.0"
ipdb = "^0.13.0"
开发环境设置
# 安装所有依赖(包括开发依赖)
poetry install
# 只安装主依赖
poetry install --only=main
# 安装主依赖和开发依赖
poetry install --with dev
# 排除特定组
poetry install --without dev
测试依赖管理
测试工具配置
# 创建测试依赖组
poetry add --group test pytest-cov
poetry add --group test pytest-mock
poetry add --group test pytest-xdist
poetry add --group test factory-boy
poetry add --group test faker
[tool.poetry.group.test]
optional = true
[tool.poetry.group.test.dependencies]
# 核心测试框架
pytest = "^7.1.0"
pytest-asyncio = "^0.19.0"
pytest-cov = "^4.0.0"
pytest-mock = "^3.8.0"
pytest-xdist = "^2.5.0"
# 测试数据生成
factory-boy = "^3.2.0"
faker = "^15.0.0"
# HTTP测试
httpx = "^0.23.0"
responses = "^0.21.0"
# 数据库测试
pytest-postgresql = "^4.1.0"
pytest-redis = "^2.4.0"
# 性能测试
pytest-benchmark = "^3.4.0"
locust = "^2.12.0"
测试配置文件
# conftest.py
import pytest
import asyncio
from httpx import AsyncClient
from app.main import app
from app.database import get_db
from app.config import get_settings
@pytest.fixture(scope="session")
def event_loop():
"""创建事件循环"""
loop = asyncio.get_event_loop_policy().new_event_loop()
yield loop
loop.close()
@pytest.fixture
async def client():
"""创建测试客户端"""
async with AsyncClient(app=app, base_url="http://test") as ac:
yield ac
@pytest.fixture
def override_get_db():
"""覆盖数据库依赖"""
# 测试数据库配置
pass
@pytest.fixture
def test_settings():
"""测试环境配置"""
return get_settings(environment="testing")
文档依赖管理
文档生成工具
# 添加文档依赖
poetry add --group docs sphinx
poetry add --group docs sphinx-rtd-theme
poetry add --group docs sphinx-autodoc-typehints
poetry add --group docs myst-parser
[tool.poetry.group.docs]
optional = true
[tool.poetry.group.docs.dependencies]
# 文档生成
sphinx = "^5.0.0"
sphinx-rtd-theme = "^1.0.0"
sphinx-autodoc-typehints = "^1.19.0"
myst-parser = "^0.18.0"
# API文档
sphinx-autoapi = "^2.0.0"
sphinxcontrib-openapi = "^0.7.0"
# 文档增强
sphinx-copybutton = "^0.5.0"
sphinx-tabs = "^3.4.0"
文档配置
# docs/conf.py
import os
import sys
sys.path.insert(0, os.path.abspath('..'))
project = 'My Project'
copyright = '2024, Your Name'
author = 'Your Name'
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.viewcode',
'sphinx.ext.napoleon',
'sphinx_autodoc_typehints',
'myst_parser',
]
html_theme = 'sphinx_rtd_theme'
html_static_path = ['_static']
# 自动文档配置
autodoc_default_options = {
'members': True,
'member-order': 'bysource',
'special-members': '__init__',
'undoc-members': True,
'exclude-members': '__weakref__'
}
自定义依赖组
创建专用依赖组
# 数据科学依赖组
poetry add --group data numpy pandas matplotlib seaborn scikit-learn
# 机器学习依赖组
poetry add --group ml tensorflow torch transformers
# 部署依赖组
poetry add --group deploy gunicorn docker-compose
# 监控依赖组
poetry add --group monitoring prometheus-client sentry-sdk
[tool.poetry.group.data]
optional = true
[tool.poetry.group.data.dependencies]
numpy = "^1.21.0"
pandas = "^1.5.0"
matplotlib = "^3.6.0"
seaborn = "^0.12.0"
scikit-learn = "^1.1.0"
jupyter = "^1.0.0"
[tool.poetry.group.ml]
optional = true
[tool.poetry.group.ml.dependencies]
tensorflow = "^2.10.0"
torch = "^1.12.0"
transformers = "^4.21.0"
datasets = "^2.5.0"
[tool.poetry.group.deploy]
optional = true
[tool.poetry.group.deploy.dependencies]
gunicorn = "^20.1.0"
docker = "^6.0.0"
kubernetes = "^24.2.0"
[tool.poetry.group.monitoring]
optional = true
[tool.poetry.group.monitoring.dependencies]
prometheus-client = "^0.14.0"
sentry-sdk = {extras = ["fastapi"], version = "^1.9.0"}
structlog = "^22.1.0"
依赖组管理命令
# 安装特定依赖组
poetry install --with data
poetry install --with ml,monitoring
# 安装多个依赖组
poetry install --with dev,test,docs
# 排除特定依赖组
poetry install --without test,docs
# 只安装可选依赖组
poetry install --only=data
# 查看特定组的依赖
poetry show --only=data
poetry show --only=ml
# 更新特定组的依赖
poetry update --only=dev
可选依赖和额外功能
可选依赖配置
[tool.poetry.dependencies]
python = "^3.8"
requests = "^2.28.0"
# 可选依赖
psycopg2-binary = {version = "^2.9.0", optional = true}
redis = {version = "^4.3.0", optional = true}
celery = {version = "^5.2.0", optional = true}
# 额外功能组
[tool.poetry.extras]
postgresql = ["psycopg2-binary"]
redis = ["redis"]
async = ["celery", "redis"]
all = ["psycopg2-binary", "redis", "celery"]
安装可选依赖
# 安装带额外功能的包
poetry install --extras "postgresql redis"
poetry install --extras "all"
# 添加可选依赖
poetry add psycopg2-binary --optional
poetry add redis --optional
# 在其他项目中使用
poetry add my-package[postgresql,redis]
条件依赖
[tool.poetry.dependencies]
python = "^3.8"
# 平台特定依赖
pywin32 = {version = "^304", markers = "sys_platform == 'win32'"}
uvloop = {version = "^0.17.0", markers = "sys_platform != 'win32'"}
# Python版本特定依赖
typing-extensions = {version = "^4.3.0", python = "<3.10"}
importlib-metadata = {version = "^4.12.0", python = "<3.8"}
环境特定配置
开发环境配置
# .env.development
DEBUG=true
DATABASE_URL=sqlite:///dev.db
REDIS_URL=redis://localhost:6379/0
LOG_LEVEL=DEBUG
# config/development.py
from .base import BaseConfig
class DevelopmentConfig(BaseConfig):
DEBUG = True
TESTING = False
# 开发数据库
DATABASE_URL = "sqlite:///dev.db"
# 开发工具
ENABLE_PROFILER = True
ENABLE_DEBUG_TOOLBAR = True
测试环境配置
# .env.testing
DEBUG=false
TESTING=true
DATABASE_URL=sqlite:///:memory:
REDIS_URL=redis://localhost:6379/1
# config/testing.py
from .base import BaseConfig
class TestingConfig(BaseConfig):
TESTING = True
DEBUG = False
# 测试数据库
DATABASE_URL = "sqlite:///:memory:"
# 禁用外部服务
CELERY_ALWAYS_EAGER = True
MAIL_SUPPRESS_SEND = True
生产环境配置
# .env.production
DEBUG=false
DATABASE_URL=postgresql://user:pass@localhost/prod
REDIS_URL=redis://redis-server:6379/0
SECRET_KEY=your-production-secret-key
# config/production.py
from .base import BaseConfig
import os
class ProductionConfig(BaseConfig):
DEBUG = False
TESTING = False
# 生产数据库
DATABASE_URL = os.getenv('DATABASE_URL')
# 安全配置
SECRET_KEY = os.getenv('SECRET_KEY')
SSL_REQUIRED = True
依赖管理策略
版本锁定策略
# 严格版本锁定(生产环境)
[tool.poetry.dependencies]
python = "3.9.15"
fastapi = "0.85.1"
uvicorn = "0.18.3"
# 兼容性版本(开发环境)
[tool.poetry.dependencies]
python = "^3.9"
fastapi = "^0.85.0"
uvicorn = "^0.18.0"
# 最小版本(库开发)
[tool.poetry.dependencies]
python = ">=3.8"
fastapi = ">=0.80.0"
依赖更新策略
# 查看过期依赖
poetry show --outdated
# 更新所有依赖
poetry update
# 更新特定依赖
poetry update fastapi uvicorn
# 更新特定组的依赖
poetry update --only=dev
poetry update --only=test
# 安全更新
poetry add safety --group dev
poetry run safety check
依赖冲突解决
# 查看依赖树
poetry show --tree
# 查看特定包的依赖
poetry show fastapi --tree
# 解决冲突
poetry lock --no-update
poetry install
# 强制重新解析
poetry lock
poetry install
实践案例
Web应用依赖管理
# Web应用的完整依赖配置
[tool.poetry.dependencies]
python = "^3.9"
# Web框架
fastapi = "^0.85.0"
uvicorn = {extras = ["standard"], version = "^0.18.0"}
# 数据库
sqlalchemy = "^1.4.0"
alembic = "^1.8.0"
asyncpg = {version = "^0.26.0", optional = true}
psycopg2-binary = {version = "^2.9.0", optional = true}
# 认证和安全
python-jose = {extras = ["cryptography"], version = "^3.3.0"}
passlib = {extras = ["bcrypt"], version = "^1.7.0"}
python-multipart = "^0.0.5"
# 配置和环境
pydantic = {extras = ["email"], version = "^1.10.0"}
python-dotenv = "^0.20.0"
[tool.poetry.group.dev.dependencies]
# 开发工具
pytest = "^7.1.0"
pytest-asyncio = "^0.19.0"
httpx = "^0.23.0"
black = "^22.0.0"
isort = "^5.10.0"
flake8 = "^5.0.0"
mypy = "^0.991"
pre-commit = "^2.20.0"
[tool.poetry.group.test.dependencies]
pytest-cov = "^4.0.0"
pytest-mock = "^3.8.0"
factory-boy = "^3.2.0"
faker = "^15.0.0"
[tool.poetry.group.deploy.dependencies]
gunicorn = "^20.1.0"
docker = "^6.0.0"
[tool.poetry.extras]
postgresql = ["asyncpg", "psycopg2-binary"]
数据科学项目依赖
[tool.poetry.dependencies]
python = "^3.9"
numpy = "^1.21.0"
pandas = "^1.5.0"
[tool.poetry.group.analysis.dependencies]
matplotlib = "^3.6.0"
seaborn = "^0.12.0"
plotly = "^5.10.0"
bokeh = "^2.4.0"
[tool.poetry.group.ml.dependencies]
scikit-learn = "^1.1.0"
xgboost = "^1.6.0"
lightgbm = "^3.3.0"
[tool.poetry.group.deep-learning.dependencies]
tensorflow = "^2.10.0"
torch = "^1.12.0"
transformers = "^4.21.0"
[tool.poetry.group.notebook.dependencies]
jupyter = "^1.0.0"
jupyterlab = "^3.4.0"
ipywidgets = "^8.0.0"
微服务项目依赖
[tool.poetry.dependencies]
python = "^3.9"
fastapi = "^0.85.0"
uvicorn = "^0.18.0"
[tool.poetry.group.database.dependencies]
sqlalchemy = "^1.4.0"
alembic = "^1.8.0"
asyncpg = "^0.26.0"
[tool.poetry.group.messaging.dependencies]
celery = "^5.2.0"
redis = "^4.3.0"
pika = "^1.3.0"
[tool.poetry.group.monitoring.dependencies]
prometheus-client = "^0.14.0"
sentry-sdk = "^1.9.0"
structlog = "^22.1.0"
[tool.poetry.group.tracing.dependencies]
opentelemetry-api = "^1.12.0"
opentelemetry-sdk = "^1.12.0"
opentelemetry-instrumentation-fastapi = "^0.33b0"
自动化脚本
依赖管理脚本
#!/bin/bash
# scripts/manage_deps.sh
case "$1" in
"install-dev")
echo "Installing development dependencies..."
poetry install --with dev,test,docs
;;
"install-prod")
echo "Installing production dependencies..."
poetry install --only=main
;;
"update-dev")
echo "Updating development dependencies..."
poetry update --only=dev
;;
"check-security")
echo "Checking for security vulnerabilities..."
poetry run safety check
poetry run bandit -r src/
;;
"check-outdated")
echo "Checking for outdated packages..."
poetry show --outdated
;;
*)
echo "Usage: $0 {install-dev|install-prod|update-dev|check-security|check-outdated}"
exit 1
;;
esac
Makefile集成
# Makefile
.PHONY: install-dev install-prod update check-deps
# 开发环境安装
install-dev:
poetry install --with dev,test,docs
poetry run pre-commit install
# 生产环境安装
install-prod:
poetry install --only=main
# 更新依赖
update:
poetry update
poetry run safety check
# 检查依赖
check-deps:
poetry show --outdated
poetry run safety check
poetry run pip-audit
# 清理环境
clean:
poetry env remove --all
poetry cache clear pypi --all
故障排除
常见依赖问题
问题1:依赖冲突
# 错误信息
# Because package-a depends on package-b (>=2.0.0)
# and package-c depends on package-b (<2.0.0), package-a is incompatible with package-c.
# 解决方案
# 1. 查看冲突详情
poetry show --tree
# 2. 更新冲突的包
poetry update package-b
# 3. 使用兼容版本
poetry add "package-a>=1.0,<2.0"
# 4. 强制重新解析
poetry lock --no-update
问题2:可选依赖未安装
# 错误信息
# ModuleNotFoundError: No module named 'psycopg2'
# 解决方案
# 1. 安装可选依赖
poetry install --extras "postgresql"
# 2. 检查extras配置
poetry show --extras
# 3. 添加到主依赖
poetry add psycopg2-binary
问题3:开发依赖在生产环境安装
# 问题:生产环境安装了开发依赖
# 解决方案
# 1. 只安装主依赖
poetry install --only=main
# 2. 排除开发依赖
poetry install --without dev,test
# 3. 检查安装的包
poetry show --only=main
调试技巧
# 详细安装信息
poetry install -vvv
# 查看解析过程
poetry lock -vvv
# 检查配置
poetry config --list
# 查看环境信息
poetry env info
# 验证配置文件
poetry check
最佳实践
依赖组织原则
- 按用途分组
# 清晰的分组策略
[tool.poetry.group.dev.dependencies] # 开发工具
[tool.poetry.group.test.dependencies] # 测试工具
[tool.poetry.group.docs.dependencies] # 文档生成
[tool.poetry.group.deploy.dependencies] # 部署工具
- 版本约束策略
# 生产依赖:保守约束
fastapi = "^0.85.0"
# 开发依赖:宽松约束
pytest = "*"
black = ">=22.0.0"
- 可选依赖设计
# 合理的可选依赖
[tool.poetry.dependencies]
psycopg2-binary = {version = "^2.9.0", optional = true}
[tool.poetry.extras]
postgresql = ["psycopg2-binary"]
环境管理策略
- 环境隔离
# 不同环境使用不同的依赖安装策略
# 开发环境
poetry install --with dev,test
# 测试环境
poetry install --with test
# 生产环境
poetry install --only=main
- 配置管理
# 环境特定的配置文件
config/
├── base.py
├── development.py
├── testing.py
└── production.py
安全考虑
- 依赖安全检查
# 定期安全检查
poetry add --group dev safety bandit
poetry run safety check
poetry run bandit -r src/
- 版本锁定
# 生产环境锁定版本
poetry export -f requirements.txt --output requirements.txt
总结
本章节详细介绍了Poetry的依赖组管理:
核心要点
- 依赖分组:合理组织不同用途的依赖包
- 环境隔离:开发、测试、生产环境的依赖分离
- 可选依赖:灵活的功能扩展机制
- 版本管理:不同环境的版本约束策略
- 自动化管理:脚本化的依赖管理流程
关键收获
- 掌握Poetry依赖组的创建和管理
- 理解不同环境下的依赖策略
- 学会使用可选依赖和额外功能
- 建立依赖安全检查机制
- 培养良好的依赖管理习惯
下一步
在下一章节011-脚本与命令管理中,我们将学习如何使用Poetry管理项目脚本和自定义命令,包括脚本配置、命令行工具开发和自动化任务管理。
更新时间: 2024-12-19 | 更新内容: 初始版本,包含完整的开发依赖与生产依赖管理指南

2413

被折叠的 条评论
为什么被折叠?



