Python中管理配置文件的最简单方式
项目描述
configzen v0.10.0
configzen – 在Python中轻松创建和维护具有验证的复杂、静态类型配置。
保持您的配置安全和一致很重要。试试 configzen 🚀
⭐ 支持 Python 3.8或更高版本,
⭐ 完全 静态类型,
⭐ 支持 YAML、JSON、TOML、INI、XML、ConfigObj、BSON、CBOR、Amazon Ion、属性 和 shellvars,
⭐ 支持完整或部分地读取和写入配置文件,具有保留原始文件结构(不包含注释[^1])的能力,
⭐ 支持配置预处理(无需更改代码即可扩展、包含和复制配置文件),
⭐ 支持变量插值(运行时值替换),
⭐ 支持具有类型验证的 模块化配置(在原地和外部包装运行时Python模块),
⭐ 支持同步和异步文件操作,
⭐ 支持从 环境变量和秘密文件 加载配置。
虽然建立在 pydantic 之上,但 configzen 继承了其大多数功能,包括 数据验证、模式生成、自定义数据类型、与 Rich 的良好集成等。
更多信息请见下文。
功能
管理内容
拥有一个如下的YAML配置文件
# database.yml
host: 127.0.0.1
port: 5432
user: postgres
您可以为此创建一个如下的 configzen 配置模型
# model.py
from ipaddress import IPv4Address, IPv6Address
from configzen import ConfigField, ConfigMeta, ConfigModel
class DatabaseConfig(ConfigModel):
host: IPv4Address | IPv6Address
port: int
user: str
password: str = ConfigField(exclude=True)
class Config(ConfigMeta):
resource = "database.yml"
env_prefix = "DB_"
db_config = DatabaseConfig.load()
您还可以从文件以及环境变量DB_HOST
、DB_PORT
、DB_USER
和DB_PASSWORD
中加载配置。由于password
字段是用exclude=True
选项创建的,它将不会包含在配置的导出数据中:这确保了您的密码永远不会在保存时泄露到database.yml
文件中——但您仍然可以通过环境变量(这里指提到的DB_PASSWORD
)传递它。还支持秘密文件,有关更多信息,请参阅pydantic 文档。
pydantic 会自然地负责解析和验证加载的数据。配置模型继承自pydantic.BaseSettings
类,因此您可以使用其所有功能:模式生成、类型转换、验证等。
不过,configzen 还提供了一些额外的功能值得一看。
您可以使用上面定义的db_config
对象来访问配置值
>>> db_config.host
IPv4Address('127.0.0.1')
如果pydantic模型验证允许的话,还可以修改它们
>>> db_config.host = "0.0.0.0"
>>> db_config.host
IPv4Address('0.0.0.0')
以及重新加载特定值,而不会影响到其他配置
>>> db_config.at("port").reload()
5432
>>> db_config
DatabaseConfig(host=IPv4Address('0.0.0.0'), port=5432, user='postgres', password='password')
>>> db_config.at("host").reload()
IPv4Address('127.0.0.1')
>>> db_config
DatabaseConfig(host=IPv4Address('127.0.0.1'), port=5432, user='postgres', password='password')
或重新加载整个配置
>>> db_config.port = 1234
>>> db_config.reload()
DatabaseConfig(host=IPv4Address('127.0.0.1'), port=5432, user='postgres', password='password')
或保存特定值,而不会影响到其他配置
>>> db_config.host = "0.0.0.0"
>>> db_config.port = 443
>>> db_config
DatabaseConfig(host=IPv4Address('0.0.0.0'), port=443, user='postgres', password='password')
>>> db_config.at("host").save()
40
>>> db_config.reload()
DatabaseConfig(host=IPv4Address('0.0.0.0'), port=5432, user='postgres', password='password')
或保存整个配置
>>> db_config.save()
39
预处理
有关支持的预处理指令,请参阅支持的预处理指令。
基本用法
有一个基础配置文件,如这样(base.json
)
{
"i18n": {
"language": "en",
"timezone": "UTC"
},
"app": {
"debug": true,
"expose": 8000
}
}
创建另一个配置文件,如这样,根据需要覆盖所需的章节
# production.yml
^extend: base.json
+app:
debug: false
并加载production.yml
配置文件。不需要在代码中明确更改以指示使用base.json
文件。
注意:在键名前使用+
会更新已在该键定义的章节,而不是完全覆盖它。
请注意,在configzen中配置文件格式并不重要:您可以使用YAML扩展JSON配置,但这也可以是其他任何受支持的格式(请参阅支持的文件格式部分)。
上面的例子相当于您使用了
# production.yml
i18n:
language: en
timezone: UTC
app:
debug: false
expose: 8000
但是有一个显著的区别:当您保存上述配置时,与基础配置文件base.json
的^extend
关系会被保留。这基本上意味着对基础配置文件所做的更改将应用于从^extend
-配置文件加载的配置模型实例。对模型进行的任何本地更改将导致自动添加带有+
的章节到导出的配置数据中。
支持的预处理指令
指令 | 引用的文件是否经过预处理? | 指令在导出时是否保留? |
---|---|---|
^extend |
是 | 是 |
^include |
是 | 否 |
^copy |
否 | 否 |
插值
基本插值
您可以在配置文件中使用插值
cpu:
cores: 4
num_workers: ${cpu.cores}
>>> from configzen import ConfigModel
...
>>> class CPUConfig(ConfigModel):
... cores: int
...
>>> class AppConfig(ConfigModel):
... cpu: CPUConfig
... num_workers: int
...
>>> app_config = AppConfig.load("app.yml")
>>> app_config
AppConfig(cpu=CPUConfig(cores=4), num_workers=4)
具有命名空间的可重用配置
您可以通过包含将独立的配置模型作为命名空间共享
# database.yml
host: ${app_config::db_host}
port: ${app_config::expose}
# app.yml
db_host: localhost
expose: 8000
>>> from configzen import ConfigModel, include
>>> from ipaddress import IPv4Address
>>>
>>> @include("app_config")
... class DatabaseConfig(ConfigModel):
... host: IPv4Address
... port: int
...
>>> class AppConfig(ConfigModel):
... db_host: str
... expose: int
...
>>> app_config = AppConfig.load("app.yml")
>>> app_config
AppConfig(db_host='localhost', expose=8000)
>>> db_config = DatabaseConfig.load("database.yml")
>>> db_config
DatabaseConfig(host=IPv4Address('127.0.0.1'), port=8000)
>>> db_config.dict()
{'host': IPv4Address('127.0.0.1'), 'port': 8000}
>>> db_config.export() # used when saving
{'host': '${app_config::db_host}', 'port': '${app_config::expose}'}
不过,您不需要传递变量名给@include
。@include
让您使用配置模型、字典及其工厂覆盖主插值命名空间或具有不同名称的(这里指app_config
)命名空间。
模块化配置
就地包装模块
您可以使用配置模型就地包装模块
- 不写模型类
# config.py
from configzen import ConfigModule
# Annotate config fields
HOST: str = "localhost"
PORT: int = 8000
ConfigModule.wrap_this_module()
- 使用模型类
# config.py
from configzen import ConfigModel
# Annotations are optional
HOST = "localhost"
PORT = 8000
class AppConfig(ConfigModel):
HOST: str
PORT: int
AppConfig.wrap_this_module()
现在值HOST
和PORT
将分别作为str
和int
数据类型进行验证
>>> import config # <configuration module 'config' from 'config.py'>
>>> config.HOST
'localhost'
>>> config.PORT
8000
>>> config.PORT = "8000"
>>> config.PORT
8000
>>> config.PORT = "abc"
Traceback (most recent call last):
...
包装可互换模块
您可以使用配置模型在模块外部包装模块
# setup.py
from configzen import ConfigModel
class AppConfig(ConfigModel):
HOST: str = "localhost"
PORT: int = 8000
config_model = AppConfig.wrap_module("config")
# config.py
HOST: str = "0.0.0.0"
PORT: int = 443
>>> from setup import config_model
>>> config_model.HOST
'0.0.0.0'
>>> config_model.PORT
443
>>> config_model.PORT = "8000"
>>> config_model.PORT
8000
>>> import config
>>> config.HOST
'0.0.0.0'
>>> config.PORT
8000
支持的文件格式
configzen 使用 anyconfig 进行数据序列化和反序列化,不操作任何特定协议的实体。例如,保存配置文件时,你的注释可能会丢失[^1],但你可以在不费劲的情况下交换文件格式。
下表显示了支持的文件格式、其要求、文件扩展名以及用于实现此目标的后端库。
文件格式 | 要使用,请安装 | 识别的文件扩展名 | 后端库 |
---|---|---|---|
JSON | - | json |
json(标准库) |
INI | - | ini 、cfg 、conf |
configparser(标准库) |
TOML | - | toml |
toml |
YAML | - | yaml 、yml |
pyyaml / ruamel.yaml |
XML | - | xml |
xml(标准库) |
ConfigObj | anyconfig-configobj-backend |
configobj |
configobj |
BSON | anyconfig-bson-backend |
bson |
bson |
CBOR(RFC 8949) | anyconfig-cbor2-backend |
cbor 、cbor2 |
cbor2 |
Amazon Ion | anyconfig-ion-backend |
ion |
ion |
CBOR(已弃用,RFC 7049) | anyconfig-cbor-backend |
cbor |
cbor |
properties | - | properties |
(本地) |
shellvars | - | shellvars |
(本地) |
如果你的文件扩展名不被识别,你可以通过调用 ConfigAgent.register_file_extension(file_extension, parser_name)
来注册自己的文件扩展名。
如果你的首选后端库不受支持,请通过报告问题来让我知道。预计未来将支持使用自定义后端。
[^1]:注释的替代建议是使用配置模型字段的 description
参数:ConfigField(description=...)
。提供的字段描述包含在默认实现的 ConfigModel.schema()
方法生成的 JSON 模式中。
设置
为了在项目中使用 configzen,请使用你的包管理器安装它,例如 pip
pip install configzen
如果你愿意为 configzen 贡献,这是很棒的,只需克隆此存储库并使用 poetry 安装其依赖项
poetry install --with dev --all-extras
之后,安装 pre-commit 插件
pre-commit install --hook-type pre-commit --hook-type pre-push
你可能还需要安装所需的存根。首先,激活你的虚拟环境
poetry shell
然后运行(在 Linux 或 PowerShell 7.0+)
mypy configzen/ || (echo yes | mypy --install-types)
或者,如果你使用的是较旧版本的 PowerShell
mypy configzen/; if (-not $?) { echo yes | mypy --install-types }
注意:如果你使用 Windows,强烈建议使用 WSL2 + pyenv(与 Python 3.8 一起)开发 configzen。
现在,你就可以开始了。🚀
欢迎贡献!当你遇到错误或功能请求时,随时 提交问题 或 提交带有更改的拉取请求。
许可
鸣谢
- @Lunarmagpie 提供了 关键的 设计建议和想法。
作者
- bswck(联系方式:bswck.dev@gmail.com 或通过 Discord
bswck
)
项目详情
下载文件
下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。