Пропустить конвертацию сущностей при загрузке строки yaml (используя PyYAML)

1

Есть ли хороший способ предотвратить преобразование объектов в объекты python при загрузке строки YAML в пакет yaml? В частности, я не хочу преобразовывать строки timestamp в объекты datetime.

Вот пример:

import yaml
yaml.load("""d: 2018-06-17\nn: 42""")

который дает

{'d': datetime.date(2018, 6, 17), 'n': 42}

но я бы хотел

{'d': '2018-06-17', n: 42}

где строка даты остается, когда строка и другие типы преобразуются. Я не хочу изменять входную строку, например, путем указания конкретных типов данных. Возможно, есть альтернативный пакет загрузчика/парсера YAML. Я использую python3.6 и PyYAML == 3.12.

Теги:
yaml

2 ответа

2
Лучший ответ

YAML имеет несколько схем и так как вы используете по умолчанию (небезопасные) нагрузки в PyYAML вы получите все конструкции на Python объектов, которые он поддерживает, в том числе и к int, что вы хотите, и один к datetime.time, что вы не" я хочу.

Поскольку вы хотите, чтобы целые числа были преобразованы, вы не можете использовать базовый загрузчик:

import yaml
data = yaml.load("""d: 2018-06-17\nn: 42""", Loader=yaml.BaseLoader)
print(data)

поскольку это дает строки везде:

{'d': '2018-06-17', 'n': '42'}

Вероятно, проще всего обрабатывать совпадающие объекты datetime в виде строк. В моей библиотеке ruamel.yaml вы можете сделать это, используя:

import ruamel.yaml

yaml = ruamel.yaml.YAML(typ='safe')
yaml.constructor.yaml_constructors[u'tag:yaml.org,2002:timestamp'] = \
   yaml.constructor.yaml_constructors[u'tag:yaml.org,2002:str']
data = yaml.load("""d: 2018-06-17\nn: 42""")
print(data)

если вам нужно только поддерживать старую спецификацию YAML 1.1, вы можете сделать то же самое в PyYAML:

import yaml
import yaml.constructor
yaml.constructor.SafeConstructor.yaml_constructors[u'tag:yaml.org,2002:timestamp'] = \
    yaml.constructor.SafeConstructor.yaml_constructors[u'tag:yaml.org,2002:str']

data = yaml.safe_load("""d: 2018-06-17\nn: 42""")
print(data)

оба печатают:

{'d': '2018-06-17', 'n': 42}
  • 0
    Если вам обоим нужна «нормальная» загрузка и отсутствие интерпретации дат, вы не можете использовать вышеуказанное решение, поскольку yaml_constructors является переменной класса. В этом случае вам нужно SafeLoader подкласс SafeLoader и использовать его .add_constructor для всех элементов, кроме timestamp
  • 0
    Это то, что я хотел. Благодарю. Есть ли хорошая документация относительно constrcutors в pyyaml?
Показать ещё 1 комментарий
0

Я думаю, что это поведение глубоко укоренилось в спецификации YAML, я пробовал ruamel, но результат тот же.

from ruamel.yaml import YAML
from datetime import date

yaml=YAML(typ="unsafe")
assert yaml.load("""d: 2018-06-17\nn: 42""") == \
       {'d': date(2018, 6, 17), 'n': 42}

Если бы у меня была эта проблема, я бы попробовал конвертировать YAML-импорт обратно с .strftime('YYYY-MM-DD') там, где это необходимо.

  • 0
    Репозиторий тегов YAML упоминается как в YAML 1.2, так и в устаревшей спецификации YAML 1.1, которой следует PyYAML. unsafe и safe загрузчики реализуют все это (и небезопасный также для конкретных языков, что делает его небезопасным). У вас также есть BaseLoader, который превращает все в строку. Поэтому я не уверен, что правильно написать, что это «глубоко укоренено в спецификации YAML».
  • 0
    @Антон: как правильно это сказать? поведение по умолчанию, разве что с использованием класса BaseLoader ?
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню