跳转到主要内容

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_HOSTDB_PORTDB_USERDB_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)命名空间。

模块化配置

就地包装模块

您可以使用配置模型就地包装模块

  1. 不写模型类
# config.py
from configzen import ConfigModule

# Annotate config fields
HOST: str = "localhost"
PORT: int = 8000

ConfigModule.wrap_this_module()
  1. 使用模型类
# config.py
from configzen import ConfigModel

# Annotations are optional
HOST = "localhost"
PORT = 8000

class AppConfig(ConfigModel):
    HOST: str
    PORT: int

AppConfig.wrap_this_module()

现在值HOSTPORT将分别作为strint数据类型进行验证

>>> 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 - inicfgconf configparser(标准库)
TOML - toml toml
YAML - yamlyml pyyaml / ruamel.yaml
XML - xml xml(标准库)
ConfigObj anyconfig-configobj-backend configobj configobj
BSON anyconfig-bson-backend bson bson
CBORRFC 8949 anyconfig-cbor2-backend cborcbor2 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。

现在,你就可以开始了。🚀

欢迎贡献!当你遇到错误或功能请求时,随时 提交问题提交带有更改的拉取请求

许可

MIT 许可证

鸣谢

作者

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源代码分发

configzen-0.10.0.tar.gz (42.2 kB 查看散列值)

上传时间 源代码

构建分发

configzen-0.10.0-py3-none-any.whl (41.3 kB 查看散列值)

上传时间 Python 3

由以下支持