有时,程序需要足够的参数,以至于将它们全部作为命令行参数或环境变量是不愉快且不可行的。在这些情况下,您将需要使用配置文件。
配置文件有几种流行的格式。其中包括历史悠久(尽管偶尔定义不足)的 INI
格式,流行但有时难以手动编写的 JSON
格式,内容广泛但细节有时令人惊讶的 YAML
格式,以及最新的成员 TOML
,许多人尚未听说过。
您的首要任务是选择一种格式,然后记录该选择。完成了这个简单的部分后,就可以解析配置了。
有时,最好有一个类来对应配置中的“抽象”数据。因为此代码不会对配置执行任何操作,所以这是显示解析逻辑的最简单方法。
想象一下文件处理器的配置:它包括一个输入目录、一个输出目录以及要拾取的文件。
配置类的抽象定义可能如下所示
from __future__ import annotations
import attr
@attr.frozen
class Configuration:
@attr.frozen
class Files:
input_dir: str
output_dir: str
files: Files
@attr.frozen
class Parameters:
patterns: List[str]
parameters: Parameters
为了简化特定于格式的代码,您还将编写一个函数来从字典中解析此类。请注意,这假设配置将使用破折号,而不是下划线。这种差异并不少见。
def configuration_from_dict(details):
files = Configuration.Files(
input_dir=details["files"]["input-dir"],
output_dir=details["files"]["output-dir"],
)
parameters = Configuration.Paraneters(
patterns=details["parameters"]["patterns"]
)
return Configuration(
files=files,
parameters=parameters,
)
JSON
JSON(JavaScript 对象表示法)是一种类似 JavaScript 的格式。
这是一个 JSON 格式的配置示例
json_config = """
{
"files": {
"input-dir": "inputs",
"output-dir": "outputs"
},
"parameters": {
"patterns": [
"*.txt",
"*.md"
]
}
}
"""
解析逻辑使用 json
模块将 JSON 解析为 Python 的内置数据结构(字典、列表、字符串),然后从字典创建类
import json
def configuration_from_json(data):
parsed = json.loads(data)
return configuration_from_dict(parsed)
INI
INI 格式最初在 Windows 上流行,后来成为事实上的配置标准。
这是相同的配置,采用 INI 格式
ini_config="""
[files]
input-dir = inputs
output-dir = outputs
[parameters]
patterns = ['*.txt', '*.md']
"""
Python 可以使用内置的 configparser
模块对其进行解析。解析器表现为类似 dict
的对象,因此可以直接传递给 configuration_from_dict
import configparser
def configuration_from_ini(data):
parser = configparser.ConfigParser()
parser.read_string(data)
return configuration_from_dict(parser)
YAML
YAML(又一种标记语言)是 JSON 的扩展,旨在更易于手动编写。它部分通过拥有冗长的规范来实现这一点。
这是相同的配置,采用 YAML 格式
yaml_config = """
files:
input-dir: inputs
output-dir: outputs
parameters:
patterns:
- '*.txt'
- '*.md'
"""
为了让 Python 解析它,您需要安装第三方模块。最流行的是 PyYAML
(pip install pyyaml
)。YAML 解析器还返回可以传递给 configuration_from_dict
的内置 Python 数据类型。但是,YAML 解析器期望一个流,因此您需要将字符串转换为流。
import io
import yaml
def configuration_from_yaml(data):
fp = io.StringIO(data)
parsed = yaml.safe_load(fp)
return configuration_from_dict(parsed)
TOML
TOML(Tom 的自有标记语言)旨在成为 YAML 的轻量级替代方案。规范更短,并且在某些地方已经很流行(例如,Rust 的包管理器 Cargo 使用它进行包配置)。
这是相同的配置,采用 TOML 格式
toml_config = """
[files]
input-dir = "inputs"
output-dir = "outputs"
[parameters]
patterns = [ "*.txt", "*.md",]
"""
为了解析 TOML,您需要安装第三方包。最流行的一个简单地称为 toml
。与 YAML 和 JSON 一样,它返回基本的 Python 数据类型。
import toml
def configuration_from_toml(data):
parsed = toml.loads(data)
return configuration_from_dict(parsed)
总结
选择配置格式是一个微妙的权衡。但是,一旦您做出决定,Python 可以使用几行代码解析大多数流行的格式。
评论已关闭。