PyYAML yaml.dump () создает сложный ключ для строкового ключа ›122 символа?

Используя 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, в зависимости от длины строкового ключа.


person Jonathan Rice    schedule 03.07.2015    source источник


Ответы (1)


Причина, по которой вы получаете явный ключевой маркер ?, заключается в том, что вы превышаете предел длины простого ключа. Это сравнивается в функции в эмиттере со 128 (длина неявного тега !!str подталкивает его к этому порогу). Вы можете переписать полную функцию, которая проверяет ключ, чтобы быть простой, но нет простого способа сделать это, поскольку значение жестко закодировано внутри функции.

Мне никогда не удавалось найти причину этого конкретного порога в YAML спецификации. Как и в источнике PyYAML, поскольку на стороне парсера он может обрабатывать такие длинные ключи (с ? или без него).

В ruamel.yaml ¹ вы можете изменить порог, изменив экземпляр дампера:

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.

person Anthon    schedule 03.07.2015