010-开发依赖与生产依赖

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

最佳实践

依赖组织原则

  1. 按用途分组
# 清晰的分组策略
[tool.poetry.group.dev.dependencies]      # 开发工具
[tool.poetry.group.test.dependencies]     # 测试工具
[tool.poetry.group.docs.dependencies]     # 文档生成
[tool.poetry.group.deploy.dependencies]   # 部署工具
  1. 版本约束策略
# 生产依赖:保守约束
fastapi = "^0.85.0"

# 开发依赖:宽松约束
pytest = "*"
black = ">=22.0.0"
  1. 可选依赖设计
# 合理的可选依赖
[tool.poetry.dependencies]
psycopg2-binary = {version = "^2.9.0", optional = true}

[tool.poetry.extras]
postgresql = ["psycopg2-binary"]

环境管理策略

  1. 环境隔离
# 不同环境使用不同的依赖安装策略
# 开发环境
poetry install --with dev,test

# 测试环境
poetry install --with test

# 生产环境
poetry install --only=main
  1. 配置管理
# 环境特定的配置文件
config/
├── base.py
├── development.py
├── testing.py
└── production.py

安全考虑

  1. 依赖安全检查
# 定期安全检查
poetry add --group dev safety bandit
poetry run safety check
poetry run bandit -r src/
  1. 版本锁定
# 生产环境锁定版本
poetry export -f requirements.txt --output requirements.txt

总结

本章节详细介绍了Poetry的依赖组管理:

核心要点

  • 依赖分组:合理组织不同用途的依赖包
  • 环境隔离:开发、测试、生产环境的依赖分离
  • 可选依赖:灵活的功能扩展机制
  • 版本管理:不同环境的版本约束策略
  • 自动化管理:脚本化的依赖管理流程

关键收获

  • 掌握Poetry依赖组的创建和管理
  • 理解不同环境下的依赖策略
  • 学会使用可选依赖和额外功能
  • 建立依赖安全检查机制
  • 培养良好的依赖管理习惯

下一步

在下一章节011-脚本与命令管理中,我们将学习如何使用Poetry管理项目脚本和自定义命令,包括脚本配置、命令行工具开发和自动化任务管理。


更新时间: 2024-12-19 | 更新内容: 初始版本,包含完整的开发依赖与生产依赖管理指南

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lvjesus

码力充电

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值