PyYAML yaml.dump() 为字符串键 > 122 个字符生成复杂键?

问题描述 投票:0回答:3

将 PyYAML 3.11 与 Python 2.7.6 结合使用,让我们转储一个简单的字典,该字典只有一个字符串键(长度为 122 个字符),映射到值“1”:

>>> print yaml.dump({'12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012': 1})
{'12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012': 1}

这正如预期一样工作 - 简单、人类可读的 YAML。但现在我们将该字符串键的长度增加到 123 个字符。现在 PyYAML 创建一个不太人类可读的复杂键,以“?”开头,并将值“1”分流到新行:

>>> print yaml.dump({'123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123': 1})
{? '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123'
  : 1}

PyYAML 为什么要这样做?有什么办法可以禁用该行为吗?这会导致我转储的 YAML 代码缺乏视觉一致性,具体取决于字符串键的长度。

python yaml pyyaml
3个回答
6
投票

您获得显式密钥标记

?
的原因是您超过了简单密钥的长度限制。在发射器中的函数中将其与 128 进行比较(隐式标签
!!str
的长度将其推过该阈值)。您可以重写检查键的完整函数以使其变得简单,但没有简单的方法可以做到这一点,因为该值是硬编码在函数内的。

我一直无法在 YAML 规范中找到 this 特定阈值的原因。在 PyYAML 源中也不行,因为在解析器端它能够处理如此长的键(有或没有

?
)。

ruamel.yaml 1 中,您可以通过更改转储器实例来更改阈值:

from __future__ import print_function

import sys
import ruamel.yaml as yaml

yaml_str = """\
- {'123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123': 1}
"""

data = yaml.load(yaml_str, Loader=yaml.RoundTripLoader)
dumper = yaml.RoundTripDumper
print('MAX_SIMPLE_KEY_LENGTH', dumper.MAX_SIMPLE_KEY_LENGTH)

yaml.dump(data, sys.stdout, Dumper=dumper)
dumper.MAX_SIMPLE_KEY_LENGTH = 256
print('After raising the threshold:')
yaml.dump(data, sys.stdout, Dumper=dumper)

会给你:

MAX_SIMPLE_KEY_LENGTH 128
- {? '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123'
  : 1}
After raising the threshold:
- {'123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123': 1}

当我通常在 80 列的终端窗口上工作时,我仍然发现那么长的按键很难阅读,当然 YMMV。尤其是在往返 YAML 时,需要对密钥以这种方式更改的时间进行精细控制。

¹ 免责声明:我是 PyYAML 增强版的作者。


0
投票

简单的问题解决:

from ruamel.yaml.emitter import Emitter
Emitter.MAX_SIMPLE_KEY_LENGTH = 1024

0
投票

在更现代的

ruamel
0.18.6
中,无需修改全局变量:

import ruamel.yaml

y = ruamel.yaml.YAML(typ='safe', pure=True)
y.emitter.MAX_SIMPLE_KEY_LENGTH = 1_000_000

y.dump(...)
© www.soinside.com 2019 - 2024. All rights reserved.