Qiu*_*ang 10 python configuration yaml toml
TOML 说: “TOML 和 YAML 都强调人类可读性特征,例如注释可以更容易地理解给定行的目的。TOML 在组合这些方面有所不同,允许注释(与 JSON 不同)但保留简单性(与 YAML 不同)。”
我可以看到 TOML 不依赖重要的空格,但除此之外,我不确定它声称的 简单性。那究竟是什么?
然后我看到StrictYAML,“StrictYAML 是一个类型安全的 YAML 解析器,它解析和验证 YAML 规范的一个受限子集。” 类型安全,那到底是什么(再次)?TOML 没有为 YAML 修复而 StrictYAML 认为他有什么问题?我确实阅读了 StrictYAML 网站上的文章,但我仍然不清楚。
所以 TOML 和 StrictYAML 都想解决 YAML 的“问题”。但是除了缩进,还有什么问题?
- - 更新 - -
我在 reddit 上发现 StrictYaml 的作者谈到了YAML 与 TOML。但到目前为止我得到的答案是“strictyaml 显示对 YAML 的理解相当差”
YAML 的缺点:
隐式类型会导致意外的类型更改。(例如,把 3 放在你之前有一个字符串的地方,它会神奇地变成一个 int)。
一堆令人讨厌的“隐藏功能”,例如节点锚点和引用,使其看起来不清楚(尽管公平地说,很多人不使用它)。
TOML的缺点:
更嘈杂的语法(尤其是多行字符串)。
数组/表的处理方式令人困惑,尤其是表数组。
我写了一个库,它删除了我不喜欢 YAML 的大部分讨厌的东西,留下了我喜欢的核心。它与一堆其他配置格式之间进行了非常详细的比较,例如:https : //github.com/crdoconnor/strictyaml/blob/master/FAQ.rst#why-not-use-toml
Mar*_*son 26
StrictYAML 类型安全——“挪威问题”
以下是 StrictYAML 人员给出的示例:
countries:
- FR
- DE
- NO
Run Code Online (Sandbox Code Playgroud)
隐式将“NO”转换为 False 值。
>>> from pyyaml import load
>>> load(the_configuration)
{'countries': ['FR', 'DE', False]}
Run Code Online (Sandbox Code Playgroud)
https://hitchdev.com/strictyaml/why/implicit-typing-removed
fly*_*lyx 17
这可能是一个固执的答案,因为我已经编写了多个 YAML 实现。
YAML 突出的语义特征是它可以表示一个可能的循环图。此外,YAML 映射可以使用复杂节点(序列或映射)作为键。当您想要表示任意数据结构时,这些功能是您可能需要的。
另一个奇特的 YAML 功能是tags。他们的目标是抽象不同编程语言中的不同类型,例如,!!map
adict
在 Python 中是 a而object
在 JavaScript 中是 a 。虽然很少显式使用,但隐式标签解析是为什么false
通常作为布尔值droggeljug
加载而作为字符串加载的原因。这里的明显目标是通过不需要!!bool false
在每个字符串值上写入布尔值或强制引号来减少噪音。
然而,现实表明很多人对此感到困惑,而 YAML 定义的yes
可能被解析为布尔值也无济于事。YAML 1.2 试图通过描述您可以使用的不同模式来解决这个问题,其中基本的“故障安全”模式专门加载到映射、序列和字符串,而更复杂的“JSON”和“核心”模式进行额外的类型猜测。然而,大多数 YAML 实现,尤其是 PyYAML,在 YAML 1.1 上保留了很长时间(许多实现最初是重写 PyYAML 代码,例如 libyaml、SnakeYAML)。这巩固了 YAML 做出需要修复的有问题的类型决策的观点。
如今,一些实现得到了改进,您可以使用故障安全模式来避免不需要的布尔值。在这方面,StrictYAML 将自身限制为故障安全模式;不要相信它的论点,即这是 PyYAML 无法做到的一些新奇事物。
YAML 实现的一个常见安全问题是它们将标签映射到任意构造函数调用(您可以在此处阅读基于此的 Ruby on Rails 漏洞利用)。请注意,这不是 YAML 的缺点;YAML 不建议在任何地方的对象构造过程中调用未知函数。这里的基本问题是数据序列化是数据封装的敌人;如果您的编程语言提供构造函数作为构造对象的唯一方法,那么这就是您在反序列化数据时需要做的。这里的补救措施只是调用已知的构造函数,这是在一系列此类漏洞利用(另一个使用 SnakeYAML iirc)浮出水面之后广泛实施的。如今,要调用未知的构造函数,您需要使用DangerLoader
在 PyYAML 中恰当命名的类。
TOML 的主要语义差异在于它不支持循环、复杂键或标签。这意味着虽然您可以在任意用户定义的类中加载 YAML,但您始终将 TOML 加载到包含数据的表或数组中。
例如,虽然YAML允许你加载{foo: 1, bar: 2}
到一个类的对象foo
和bar
整型字段,TOML总是这样加载到一个表。您通常在文档中发现的 YAML 功能的一个突出示例是它可以将标量加载1d6
到对象中{number: 1, sides: 6}
;TOML 将始终将其加载为 string "1d6"
。
TOML 在这里被认为的简单性是它不做 YAML 做的一些事情。例如,如果您使用静态类型语言(如 Java),则在加载{foo: 1, bar: 2}
到对象后myObject
,您可以myObject.foo
安全地访问(获取整数1
)。如果您使用了 TOML,则需要这样做myObject["foo"],
,如果密钥不存在,则可能会引发异常。这在 Python 等脚本语言中不太正确:这里,myObject.foo
如果foo
不是myObject.
我在这里回答很多 YAML 问题的观点是,人们不使用 YAML 的功能,并且经常将所有内容加载到类似Map<String, Object>
(以 Java 为例)的结构中,然后从那里获取。如果你这样做,你也可以使用 TOML。
TOML 提供了另一种简单的语法:由于它比 YAML 简单得多,因此更容易发出用户可以理解的错误。例如,YAML 语法错误中的常见错误文本是“在此上下文中不允许映射值”(尝试在 SO 上搜索以查找大量问题)。你在这里得到这个例子:
foo: 1
bar: 2
Run Code Online (Sandbox Code Playgroud)
错误消息不能帮助用户修复错误。这是因为 YAML 的复杂语法:YAML 认为1
并且bar
是多行标量的一部分(因为bar:
缩进超过foo:
),将它们放在一起,然后看到第二个:
并失败,因为多行标量可能不会用作隐式键。然而,最有可能的是,用户要么是缩进的,要么是bar:
认为他们可以给 foo ( 1
) 和一些孩子一个标量值。由于 YAML 语法的可能性,很难编写可以帮助用户的错误消息。
由于 TOML 的语法要简单得多,因此错误消息更容易理解。如果编写 TOML 的用户不是具有语法分析背景的人,那么这是一个很大的优势。
TOML 比 YAML 有一个概念上的优势:由于它的结构允许较少的自由度,它往往更容易阅读。在阅读 TOML 时,您总是知道,“好吧,我将在其中包含带有值的嵌套表”,而使用 YAML,您有一些任意结构。我相信这在阅读 YAML 文件时需要更多的认知负荷。
StrictYAML 认为它提供了类型安全性,但由于 YAML 不是一种编程语言,并且特别不支持赋值,因此基于由 StrictYAML 链接的维基百科定义,这种说法没有任何意义(类型安全性来使用您使用的编程语言;例如,任何 YAML 在将其加载到适当的 Java 类实例中后都是类型安全的,但在 Python 之类的语言中,您永远不会是类型安全的)。回顾其已删除功能列表,它显示对 YAML 的理解相当差:
在反序列化方面,
所有数据都是字符串、列表或 OrderedDict
它基本上与 TOML 支持的结构相同(我相信 StrictYAML 支持映射中的复杂键,因为在 Python 中既不能list
也不能哈希OrderedDict
)。
您还失去了反序列化为预定义类结构的能力。有人可能会说,由于无法构造一个类的对象具有良好定义的两个领域,因此StrictYAML较少类型安全比标准YAML:标准的YAML实现能保证返回的对象由类型描述一定的结构,而StrictYAML让你在每级别可以是字符串、列表或 OrderedDict 并且您不能做任何事情来限制它。
虽然它的一些论点有缺陷,但由此产生的语言仍然可用。例如,使用 StrictYAML,您无需关心困扰某些 YAML 实现的十亿笑声攻击。同样,这不是 YAML 问题而是实现问题,因为 YAML 不需要实现来复制从多个位置锚定和引用的节点。
相当多的 YAML 问题源于糟糕的实现,而不是语言本身的问题。然而,YAML 作为一种语言肯定是复杂的,并且语法错误可能难以理解,这可能是使用像 TOML 这样的语言的正当理由。至于 StrictYAML,它确实提供了一些好处,但我建议不要使用它,因为它没有适当的规范,而且只有一个实现,这是一个很容易成为维护噩梦的设置(项目可能会中断,破坏更改很容易)。
归档时间: |
|
查看次数: |
5838 次 |
最近记录: |