Python脚本如何读取本地配置文件:从入门到生产级实战
目录导读
- 为什么需要配置文件? — 项目可维护性与环境分离的核心思想
- 主流配置文件格式对比 — INI、JSON、YAML、TOML 选型指南
- Python内置模块实战 —
configparser读取 INI 文件全流程 - JSON配置读取与异常处理 — 适合API交互场景的最简方案
- YAML配置读取 — 借助
PyYAML实现复杂层级配置 - 环境变量与配置文件协同 — 敏感信息不硬编码的进阶技巧
- 常见问题与解决方案 — 编码、路径、热加载等痛点修复
- 生产环境最佳实践 — 配置校验、加密与多环境管理
为什么需要配置文件?
问:脚本写得好好的,为什么非要搞个配置文件?
答: 假设你的脚本连接数据库时,密码写死在代码里,一旦密码变更,你需要改代码、重新部署、重启服务,而使用配置文件后,只需修改一个外部文件,无需触碰核心逻辑,这叫配置与代码分离,是构建可维护系统的第一原则。

配置文件的核心价值在于:
- 环境隔离:开发、测试、生产环境使用不同配置(数据库地址、API密钥等)
- 扩展性:新增参数(如日志级别、超时时间)无需修改代码
- 安全合规:敏感信息可通过环境变量或加密文件注入,而非提交到版本库
主流配置文件格式对比
问:Python支持那么多格式,该选哪种?
答: 根据项目规模与团队习惯选择,以下是四种常见格式的对比表:
| 格式 | 适用场景 | 优点 | 缺点 | 标准库支持 |
|---|---|---|---|---|
| INI | 简单项目、传统应用 | 结构直观,Python内置configparser |
不支持复杂嵌套 | |
| JSON | Web项目、API接口 | 序列化方便,易与其他语言交互 | 写起来啰嗦,不支持注释 | |
| YAML | 大数据、DevOps、Kubernetes | 层级清晰,支持注释与引用 | 缩进敏感,需第三方库 | ❌(需PyYAML) |
| TOML | 现代项目(如pip配置) | 明确的数据类型,可读性强 | 社区使用度较低 | ✅(Python3.11+) |
小原则:
- 如果你写的是十行以内的脚本 → INI 或 JSON
- 如果你在写企业级服务 → YAML 或 TOML
Python内置模块实战:读取INI文件
问:INI配置文件长什么样?
答: 见下方示例 config.ini:
[DEFAULT] log_level = INFO timeout = 30 [database] host = 127.0.0.1 port = 5432 user = admin password = secret123
Python脚本读取代码:
import configparser
config = configparser.ConfigParser()
config.read('config.ini', encoding='utf-8')
# 读取数据库配置
db_host = config['database']['host']
db_port = config.getint('database', 'port') # 自动转为int
log_level = config['DEFAULT']['log_level']
print(f"连接数据库:{db_host}:{db_port}")
注意点:
read()可传入list路径,优先读取存在的文件- 一定要指定
encoding='utf-8',否则中文路径或注释可能报错 [DEFAULT]节下的配置会作为其他节的默认值,无需重复定义
JSON配置读取与异常处理
问:JSON配置文件怎么读更安全?
答: config.json 内容示例:
{
"server": {
"host": "0.0.0.0",
"port": 8000,
"cors": ["https://example.com"]
}
}
Python脚本:
import json
from pathlib import Path
config_path = Path('config.json')
if not config_path.exists():
raise FileNotFoundError(f"配置文件 {config_path} 不存在")
try:
with open(config_path, 'r', encoding='utf-8') as f:
config = json.load(f)
except json.JSONDecodeError as e:
print(f"配置解析失败:{e}")
exit(1)
port = config.get('server', {}).get('port', 8080)
print(f"服务端口:{port}")
关键优化:
- 使用
.get()方法避免 KeyError,并设置默认值 - 用
Path处理路径,跨系统更安全 - 解析失败时给出明确错误信息,方便调试
YAML配置读取:复杂层级的最佳选择
问:YAML配置文件怎么读取?
答: 需要安装 PyYAML 库:pip install pyyaml,配置文件 config.yaml:
database:
host: 192.168.1.100
port: 5432
pool_size: 10
options:
connect_timeout: 5
keepalives: true
logging:
level: DEBUG
file: /var/log/app.log
Python读取代码:
import yaml
with open('config.yaml', 'r', encoding='utf-8') as f:
config = yaml.safe_load(f) # 推荐使用 safe_load 而非 load
db_host = config['database']['host']
timeout = config['database']['options']['connect_timeout']
常见坑:
- 永远使用
yaml.safe_load(),不要用yaml.load(),后者可能执行任意代码 - YAML对缩进极其敏感,建议用编辑器格式化
- 支持 注释,非常适合大型配置文档
环境变量与配置文件协同
问:配置文件中有密码,提交到GitHub怎么办?
答: 核心策略——配置文件存结构,环境变量存敏感值。
配置模板 + .env 文件
新建 config.template.json:
{
"database": {
"host": "localhost",
"user": "admin",
"password": "${DB_PASSWORD}"
}
}
使用 os.environ 读取环境变量:
import os, json
with open('config.json') as f:
raw = f.read()
# 替换 ${KEY} 格式的占位符
for key, value in os.environ.items():
raw = raw.replace(f'${{{key}}}', value)
config = json.loads(raw)
使用 python-dotenv(推荐)
创建 .env 文件(绝不可提交):
DB_PASSWORD=real_secret_123
代码中加入加载逻辑:
from dotenv import load_dotenv
load_dotenv() # 自动加载 .env 文件到环境变量
db_password = os.getenv('DB_PASSWORD')
最佳实践:
将 config.template.json 和 .env.example 提交到Git,真正的 .env 和 config.json 加入 .gitignore。
常见问题与解决方案
问题1:配置文件路径总是找不到?
解决方案: 使用 __file__ 获取脚本所在路径:
from pathlib import Path BASE_DIR = Path(__file__).resolve().parent config_path = BASE_DIR / 'config.ini'
问题2:读取中文配置时报错?
解决方案: 始终以 encoding='utf-8' 打开文件,如果文件是 GBK 编码,需指定 encoding='gbk'。
问题3:配置修改后脚本不生效?
解决方案: 配置文件通常是程序启动时一次读取,若需热加载,可定时检查文件修改时间:
import os, time
last_mtime = 0
def check_config():
global config, last_mtime
mtime = os.path.getmtime('config.ini')
if mtime > last_mtime:
config = configparser.ConfigParser()
config.read('config.ini')
last_mtime = mtime
问题4:JSON文件不支持注释?
解决方案: 使用 JSON 格式时,可以在读取前用正则忽略以 或 开头的行,但更推荐改用 YAML。
生产环境最佳实践
配置校验是必须的
使用 pydantic 库定义配置模型的类型与约束:
from pydantic import BaseModel, Field
class DatabaseConfig(BaseModel):
host: str
port: int = Field(5432, ge=1024, le=65535)
password: str = Field(min_length=8)
class AppConfig(BaseModel):
database: DatabaseConfig
# 读取文件并校验
config = yaml.safe_load(open('config.yaml'))
validated_config = AppConfig(**config)
敏感配置应加密
对密码或密钥使用 cryptography 库进行对称加密,运行时解密。
多环境管理方案
项目目录结构推荐:
project/
├── config/
│ ├── base.yaml # 公共配置
│ ├── development.yaml # 开发环境覆盖
│ ├── production.yaml # 生产环境覆盖
├── .env.development # 开发环境变量
├── .env.production # 生产环境变量
启动时根据 ENV 环境变量合并配置:
import os
env = os.getenv('APP_ENV', 'development')
# 合并 base 与对应环境配置
版本库中只存模板
# .gitignore 中必须包含: config.json .env *.key
Python脚本读取配置文件看似简单,但做好却需要考量编码、路径、安全、多环境等多方面因素,从最初的 configparser 到现代项目的 pydantic + yaml + env 组合,核心目标始终是将可变部分抽离出来,确保代码的稳定与安全,希望这篇文章能帮你建立一套可落地的配置管理思路。
如果你在实际项目中遇到特殊的配置读取需求(如远程配置中心、动态配置刷新),欢迎在评论区留言讨论。