本文目录导读:

为Python脚本适配多环境配置(开发、测试、生产等),有几种成熟的方法,以下是常用的实现方案:
使用环境变量(推荐)
基础实现
import os
from dotenv import load_dotenv
# 加载.env文件
load_dotenv()
class Config:
# 数据库配置
DB_HOST = os.getenv('DB_HOST', 'localhost')
DB_PORT = int(os.getenv('DB_PORT', '5432'))
DB_NAME = os.getenv('DB_NAME', 'myapp')
DB_USER = os.getenv('DB_USER', 'admin')
DB_PASSWORD = os.getenv('DB_PASSWORD', '')
# 应用配置
DEBUG = os.getenv('DEBUG', 'False').lower() == 'true'
SECRET_KEY = os.getenv('SECRET_KEY', 'default-secret-key')
API_URL = os.getenv('API_URL', 'http://localhost:8000')
# 使用配置
config = Config()
print(f"当前环境: {os.getenv('ENV', 'development')}")
print(f"数据库: {config.DB_HOST}:{config.DB_PORT}")
多环境配置文件
# config.py
import os
from dotenv import load_dotenv
class BaseConfig:
"""基础配置"""
SECRET_KEY = os.getenv('SECRET_KEY', 'default-key')
API_TIMEOUT = 30
class DevelopmentConfig(BaseConfig):
"""开发环境"""
DEBUG = True
DB_URI = 'sqlite:///dev.db'
API_URL = 'http://localhost:8000'
class TestingConfig(BaseConfig):
"""测试环境"""
TESTING = True
DB_URI = 'sqlite:///test.db'
API_URL = 'http://test-api.example.com'
class ProductionConfig(BaseConfig):
"""生产环境"""
DEBUG = False
DB_URI = os.getenv('DATABASE_URL')
API_URL = 'https://api.example.com'
# 配置映射
config_map = {
'development': DevelopmentConfig,
'testing': TestingConfig,
'production': ProductionConfig,
'default': DevelopmentConfig
}
def get_config():
env = os.getenv('FLASK_ENV', 'development')
config_class = config_map.get(env, config_map['default'])
return config_class()
# 使用
config = get_config()
print(f"当前环境: {os.getenv('FLASK_ENV', 'development')}")
print(f"数据库: {config.DB_URI}")
使用YAML配置文件
目录结构
project/
├── config/
│ ├── default.yaml
│ ├── development.yaml
│ ├── production.yaml
│ └── testing.yaml
└── app.py
配置加载
import yaml
import os
class ConfigLoader:
def __init__(self, env=None):
self.env = env or os.getenv('APP_ENV', 'development')
self.config = {}
self._load_config()
def _load_config(self):
config_dir = os.path.join(os.path.dirname(__file__), 'config')
# 加载默认配置
default_path = os.path.join(config_dir, 'default.yaml')
if os.path.exists(default_path):
with open(default_path, 'r') as f:
self.config.update(yaml.safe_load(f))
# 加载环境特定配置
env_path = os.path.join(config_dir, f'{self.env}.yaml')
if os.path.exists(env_path):
with open(env_path, 'r') as f:
self.config.update(yaml.safe_load(f))
# 环境变量覆盖(优先级最高)
self._override_with_env()
def _override_with_env(self):
"""环境变量覆盖配置"""
for key in self.config:
env_key = key.upper()
if env_key in os.environ:
self.config[key] = os.environ[env_key]
def __getattr__(self, name):
if name in self.config:
return self.config[name]
raise AttributeError(f"配置项 '{name}' 不存在")
# 使用示例
config = ConfigLoader()
print(f"数据库: {config.database}")
print(f"API密钥: {config.api_key}")
YAML配置文件示例
# config/default.yaml
database:
host: localhost
port: 5432
name: myapp
user: admin
redis:
host: localhost
port: 6379
api:
timeout: 30
retry: 3
# config/development.yaml
database:
name: myapp_dev
debug: true
# config/production.yaml
database:
host: ${DB_HOST}
name: myapp_prod
debug: false
使用配置类(更面向对象)
from dataclasses import dataclass, field
from typing import Optional
import os
from dotenv import load_dotenv
load_dotenv()
@dataclass
class DatabaseConfig:
host: str = 'localhost'
port: int = 5432
name: str = 'myapp'
user: str = 'admin'
password: str = ''
@classmethod
def from_env(cls):
return cls(
host=os.getenv('DB_HOST', 'localhost'),
port=int(os.getenv('DB_PORT', '5432')),
name=os.getenv('DB_NAME', 'myapp'),
user=os.getenv('DB_USER', 'admin'),
password=os.getenv('DB_PASSWORD', '')
)
@dataclass
class AppConfig:
debug: bool = False
secret_key: str = 'default'
api_url: str = 'http://localhost:8000'
database: DatabaseConfig = field(default_factory=DatabaseConfig)
@classmethod
def create(cls, env: Optional[str] = None):
env = env or os.getenv('APP_ENV', 'development')
if env == 'production':
return cls(
debug=False,
secret_key=os.getenv('SECRET_KEY', ''),
api_url='https://api.example.com',
database=DatabaseConfig.from_env()
)
elif env == 'testing':
return cls(
debug=True,
database=DatabaseConfig(
name='myapp_test',
host='localhost'
)
)
else: # development
return cls(
debug=True,
database=DatabaseConfig(
name='myapp_dev',
host='localhost'
)
)
# 使用
config = AppConfig.create()
print(f"调试模式: {config.debug}")
print(f"数据库: {config.database.host}:{config.database.port}/{config.database.name}")
使用配置管理库
安装 python-dotenv + configobj
pip install python-dotenv configobj
配置文件结构
# config/development.ini [app] debug = true secret_key = dev-secret-key [database] host = localhost port = 5432 name = myapp_dev [api] url = http://localhost:8000 timeout = 30
配置加载器
from configobj import ConfigObj
import os
from pathlib import Path
class Config:
_instance = None
_config = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._load()
return cls._instance
def _load(self):
env = os.getenv('APP_ENV', 'development')
config_path = Path(__file__).parent / 'config' / f'{env}.ini'
if not config_path.exists():
raise FileNotFoundError(f"配置文件不存在: {config_path}")
self._config = ConfigObj(str(config_path))
# 环境变量覆盖
self._override_with_env()
def _override_with_env(self):
"""环境变量覆盖配置"""
for section, values in self._config.items():
for key in values:
env_key = f"{section.upper()}_{key.upper()}"
if env_key in os.environ:
self._config[section][key] = os.environ[env_key]
def get(self, section, key, default=None):
try:
return self._config[section][key]
except KeyError:
return default
def __getattr__(self, name):
if name in self._config:
return self._config[name]
raise AttributeError(f"配置项 '{name}' 不存在")
# 单例使用
config = Config()
print(f"数据库: {config['database']['host']}")
print(f"调试: {config.get('app', 'debug', 'false')}")
推荐的最佳实践
项目结构
project/
├── config/
│ ├── __init__.py
│ ├── base.py
│ ├── development.py
│ ├── production.py
│ └── testing.py
├── .env
├── .env.development
├── .env.production
├── app.py
└── requirements.txt
完整的配置管理
# config/__init__.py
import os
from dotenv import load_dotenv
def load_config():
"""加载当前环境的配置"""
env = os.getenv('APP_ENV', 'development')
# 加载环境特定的.env文件
env_file = f'.env.{env}'
if os.path.exists(env_file):
load_dotenv(env_file)
# 加载基础.env文件
if os.path.exists('.env'):
load_dotenv('.env')
# 动态导入对应环境的配置模块
if env == 'production':
from .production import ProductionConfig
return ProductionConfig()
elif env == 'testing':
from .testing import TestingConfig
return TestingConfig()
else:
from .development import DevelopmentConfig
return DevelopmentConfig()
# config/base.py
class BaseConfig:
SECRET_KEY = os.getenv('SECRET_KEY')
SQLALCHEMY_TRACK_MODIFICATIONS = False
# config/development.py
from .base import BaseConfig
class DevelopmentConfig(BaseConfig):
DEBUG = True
SQLALCHEMY_DATABASE_URI = os.getenv('DEV_DATABASE_URL',
'sqlite:///dev.db')
# app.py
from config import load_config
config = load_config()
app.config.from_object(config)
.env文件示例
# .env.development (开发环境) APP_ENV=development SECRET_KEY=dev-secret-key-123 DATABASE_URL=postgresql://localhost:5432/myapp_dev DEBUG=True API_URL=http://localhost:8000 # .env.production (生产环境) APP_ENV=production SECRET_KEY=prod-secret-key-456 DATABASE_URL=postgresql://user:pass@prod-db:5432/myapp DEBUG=False API_URL=https://api.example.com
启动脚本示例
# 开发环境 export APP_ENV=development && python app.py # 生产环境 export APP_ENV=production && python app.py # 或使用.env文件 APP_ENV=development python app.py
| 方法 | 优点 | 适用场景 |
|---|---|---|
| 环境变量 | 简单、安全、12-Factor | 云部署、容器化 |
| YAML/INI文件 | 结构化、易维护 | 复杂配置、团队协作 |
| 配置类 | 类型安全、IDE支持 | 中型项目 |
| 配置管理库 | 功能完整、可靠性高 | 大型项目 |
推荐方案:结合使用 环境变量 + YAML配置文件,既保证了灵活性,又便于团队协作,对于简单项目,单独使用环境变量即可。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播