严格的 YAML 解析器:StrictYAML 使用指南
StrictYAML 是一个类型安全的 YAML 解析器,它拒绝解析 YAML 中不安全的功能,并提供严格的标记验证和类型转换。它具有优美的 API,清晰的异常信息,并支持修改和写回 YAML 文件,同时保留注释。可以使用 schema 进行数据验证,如果存在语法错误或 schema 违例,会抛出异常。 StrictYAML 旨在提供更安全、更易于维护的 YAML 解析体验,并提供了丰富的验证器和使用指南。
StrictYAML
StrictYAML 是一个类型安全的 YAML 解析器,它解析并验证 YAML 规范的一个受限子集。
主要特性:
- 优美的 API
- 拒绝解析 YAML 中丑陋、难以阅读且不安全的功能,例如 Norway problem。
- 严格的标记验证和直接的类型转换。
- 清晰易读的异常信息,包含代码片段和行号。
- 可以作为
pyyaml
、ruamel.yaml
或poyo
的近似替代品。 - 能够读取 YAML,进行修改并写回,同时保留注释。
- 当前不以速度为优先。
简单示例:
# All about the character
name:Ford Prefect
age:42
possessions:
-Towel
from strictyaml import load, Map, Str, Int, Seq, YAMLError
默认解析结果:
>>> load(yaml_snippet)
YAML({'name': 'Ford Prefect', 'age': '42', 'possessions': ['Towel']})
所有数据都是字符串、列表或 OrderedDict 类型:
>>> load(yaml_snippet).data
{'name': 'Ford Prefect', 'age': '42', 'possessions': ['Towel']}
使用 schema 的快速入门:
from strictyaml import load, Map, Str, Int, Seq, YAMLError
schema = Map({"name": Str(), "age": Int(), "possessions": Seq(Str())})
42 现在被解析为整数:
>>> person = load(yaml_snippet, schema)
>>> person.data
{'name': 'Ford Prefect', 'age': 42, 'possessions': ['Towel']}
如果存在语法问题、违反 schema 或使用了不允许的 YAML 特性,将会抛出 YAMLError 异常:
# All about the character
name:Ford Prefect
age:42
例如,一个 schema 违例:
try:
person = load(yaml_snippet, schema)
except YAMLError as error:
print(error)
while parsing a mapping
in "<unicode string>", line 1, column 1:
# All about the character
^ (line:1)
required key(s) 'possessions' not found
in "<unicode string>", line 3, column 1:
age:'42'
^ (line:3)
如果解析正确:
from strictyaml import load, Map, Str, Int, Seq, YAMLError, as_document
schema = Map({"name": Str(), "age": Int(), "possessions": Seq(Str())})
您可以修改值并写出 YAML,同时保留注释:
person = load(yaml_snippet, schema)
person['age'] = 43
print(person.as_yaml())
# All about the character
name:Ford Prefect
age:43
possessions:
-Towel
以及查找行号:
>>> person = load(yaml_snippet, schema)
>>> person['possessions'][0].start_line
5
还可以从 dict 或 list 构建 YAML 文档:
print(as_document({"x": 1}).as_yaml())
x:1
安装
$ pip install strictyaml
为什么选择 StrictYAML?
有许多格式和方法可以实现与 StrictYAML 大致相同的目的。 我已尝试使其成为最好的一个。 以下是一系列有据可查的理由:
- 为什么避免将环境变量用作配置?
- 为什么不使用 HJSON?
- 为什么不使用 HOCON?
- 为什么不使用 INI 文件?
- 为什么不使用 JSON Schema 进行验证?
- 为什么不将 JSON 用于简单的配置文件?
- 为什么不使用 JSON5?
- 为什么不使用 YAML 1.2 标准? - 我们不需要新的标准!
- 为什么不使用 kwalify 与标准 YAML 来验证我的 YAML?
- 为什么不使用 Python 的 schema 库(或类似的)进行验证?
- 为什么不使用 SDLang?
- TOML 有什么问题?
- 为什么我不应该只使用 Python 代码进行配置?
- 为什么不使用 XML 进行配置或 DSL?
使用 StrictYAML
使用方法:
- 从代码从头开始构建 YAML 文档
- 对不同但同样有效的 YAML 类型进行 Either/or schema 验证
- 标记异常
- 合并 YAML 文档
- 重新验证已经验证的文档
- 读取 YAML、编辑它并写回
- 获取 YAML 元素的行号
- 在没有 schema 的情况下解析 YAML
复合验证器:
- 固定长度序列 (FixedSeq)
- 结合了定义和未定义键的映射 (MapCombined)
- 具有任意键名的映射 (MapPattern)
- 具有定义键和自定义键验证器的映射 (Map)
- 使用已解析映射的 YAML 对象
- 具有定义键的映射 (Map)
- 带有默认值的可选键 (Map/Optional)
- 验证映射中的可选键 (Map)
- 唯一项序列 (UniqueSeq)
- 序列/列表验证器 (Seq)
- 使用 schema 更新文档
标量验证器:
- 布尔值 (Bool)
- 解析逗号分隔的项目 (CommaSeparated)
- 日期时间 (Datetime)
- 十进制数 (Decimal)
- Email 和 URL 验证器
- 空键验证
- 枚举标量 (Enum)
- 浮点数 (Float)
- 十六进制整数 (HexInt)
- 整数 (Int)
- 使用正则表达式验证字符串 (Regex)
- 解析字符串 (Str)
限制:
设计依据
StrictYAML 中有一些有争议和/或不明显的设计决策。 这些记录在此处:
- 重复的键有什么问题?
- 显式标签有什么问题?
- 流式 YAML 有什么问题?
- 挪威问题 - 为什么 StrictYAML 拒绝进行隐式类型转换,您也应该这样做
- 节点锚点和引用有什么问题?
- 为什么 StrictYAML 不解析 Python 对象的直接表示?
- 为什么 StrictYAML 只从字符串而不是文件解析?
- 为什么解析速度不是 StrictYAML 的首要任务?
- 什么是语法类型?
- 为什么 StrictYAML 让您在 Python(一种图灵完备语言)中定义 schema?
Star 贡献者
- @wwoods
- @chrisburr
- @jnichols0
其他贡献者
- @eulores
- @WaltWoods
- @ChristopherGS
- @gvx
- @AlexandreDecan
- @lots0logs
- @tobbez
- @jaredsampson
- @BoboTIG
StrictYAML 还包含来自 ruamel.yaml 的代码,版权所有 Anthon van der Neut。
贡献
- 在编写任何代码之前,请阅读有关向 hitchdev 库贡献的教程。
- 在编写任何代码之前,如果您要提出新功能,请在 github 上提出。 如果是现有功能/错误,请评论并简要描述您将如何实现它。
- 所有代码都需要附带一个 story 来练习它,或者修改现有的 story。 这既用于测试代码,也用于构建文档。
Copyright © 2018 - 2023 Colm O'Connor
由 Material for MkDocs 构建。