Как читать / загружать параметры yaml с ведущими нулями в виде строки? - PullRequest
0 голосов
/ 22 февраля 2019

Как читать / загружать параметры YAML с ведущими нулями в виде строки и манипулировать в python 3.7?Из инструмента C ++, использующего yaml-cpp (yaml 1.2), я получаю текстовый файл, содержащий leading_zero: 00005.Чтение / загрузка этой строки кода, похоже, преобразуется в int, но почему?Знаете ли вы, как обрабатывать строки YAML с ведущими нулями?

ruamel.yaml (yaml 1.2)

import sys
from ruamel.yaml import YAML

yaml = YAML()
inp = "leading_zero: 00005\n"
code = yaml.load(inp)
print(code)
print(code['leading_zero'])
yaml.dump(code, sys.stdout)

выходной ruamel.yaml

ordereddict([('leading_zero', 5)])
5
leading_zero: 00005

Как вы можетесм. 00005 не сохраняется как строка '00005' в указанном порядке, но почему тогда yaml.dump() показывает правильное число?

pyyaml ​​(yaml 1.1)

import yaml
inp = "leading_zero: 00005\n"
code = yaml.load(inp)
print(code)
print(yaml.dump(code, default_flow_style=False))

output pyyaml ​​

{'leading_zero': 5}
leading_zero: 5

1 Ответ

0 голосов
/ 22 февраля 2019

Прежде всего, нет строк YAML, есть коллекции (отображения и последовательности) и скаляры.Предполагая, что эти скаляры не помечены (как в вашем случае), они могут быть заключены в кавычки (для простоты это включает в себя буквальный / сложенный стиль) или обычный.

В обычном случае загрузки документа YAML,цитируемый скаляр будет загружен как строки, а простой скаляр открыт для интерпретации как специальный тип в зависимости от его «содержимого».Такая интерпретация может привести к тому, что это будет логическое значение, дата, значение с плавающей запятой.Если ничего из этого не совпадает, простой скаляр загружается в виде строки.

В обычном случае загрузки применяется Базовая схема .Эта схема является надмножеством схемы JSON, и в обоих простых скалярах, состоящих только из чисел, предполагается, что они загружены как целых чисел .Таким образом, это отвечает на ваш первый вопрос о том, как обрабатывать «строки YAML»

ruamel.yaml, используя режим по умолчанию (туда-обратно), пытается сохранить определенный формат вашего документа YAML, если вы загружаете, а затем выгрузитедокумент (это не всегда возможно, но он пытается).Хотя он загружает 00005 как целое число, на самом деле он является подтипом целочисленного класса, который включает в себя информацию о формате целого числа (т. Е. Включая число ведущих нулей).Если ваш документ YAML находится под контролем ревизии, хорошо, что такого рода вещи не меняются только потому, что вы обновили какую-то другую часть документа.

Это должно ответить на ваш второй вопрос, спрашивающий, почему отображается ruamel.yamlправильный скаляр на выходе.

PyYAML этого не делает (как и ruamel.yaml, если решено использовать загрузку safe).И вам повезло, что вы применили скаляр как 00005 для своего теста, потому что 00008 будет загружаться как строка (поскольку PyYAML использует спецификацию YAML 1.1 до 2009 года, в которой начальный ноль указывает восьмеричное значение, в восьмеричных YAML 1.2начинаются с 0o) и 00015 загружаются в ruamel.yaml как число 15 и в PyYAML как число 13:

import sys
import ruamel.yaml
import yaml as pyyaml

yaml_str = """\
- 00005    
- 00008    # this is not an octal in YAML 1.1
- 00015
"""

yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
print('ruamel.yaml:', data, type(data[0]))
yaml.dump(data, sys.stdout)
print('-----------')
data = pyyaml.load(yaml_str)
print('pyyaml:     ', data, type(data[0]))
pyyaml.dump(data, sys.stdout, default_flow_style=False)

, что дает:

ruamel.yaml: [5, 8, 15] <class 'ruamel.yaml.scalarint.ScalarInt'>
- 00005
- 00008    # this is not an octal in YAML 1.1
- 00015
-----------
pyyaml:      [5, '00008', 13] <class 'int'>
- 5
- 00008
- 13

Знаю ли я, как обрабатывать «строки yaml с ведущими нулями», нет, я не знаю, но я даю вам несколько вариантов на выбор, в зависимости от цели, с которой вы загружаете документ (просто чтобы прояснить: яЯ являюсь автором ruamel.yaml).

  • В стандартном режиме туда-обратно я загружаю их как вещи, которые ведут себя как целые числа, но сохраняют внешний вид, специфичный для ввода, какYAML предоставляет множество способов представить любое конкретное число, например 5.

  • Если вы загрузите после выполнения yaml = YAML(typ='safe'), у вас просто будут простые числа, которые не сбрасывают с ведущими нулями.

  • Если вызагрузить после выполнения `yaml = YAML (typ = 'base'), вы получите базовый загрузчик и каждый скаляр загружается в виде строки

в виде программы:

from ruamel.yaml import YAML

for t in ['rt', 'safe', 'base']:   # 'rt' is the default
    data = YAML(typ=t).load("00005")
    dt = type(data)
    print(f'{t:5}  {data!r:7}  {dt}')

дает:

rt     5        <class 'ruamel.yaml.scalarint.ScalarInt'>
safe   5        <class 'int'>
base   '00005'  <class 'str'>

, поэтому, если вам не нравятся магические "целые числа" режима кругового обхода, загрузите базовую схему и обработайте полученную строку, загруженную из скаляра YAML самостоятельно.Альтернативой для этого может быть выгрузка регулярного выражения с целочисленным соответствием из безопасного или двустороннего режима, но это более сложно.

...