Есть ли хороший способ предотвратить преобразование объектов в объекты 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 имеет несколько схем и так как вы используете по умолчанию (небезопасные) нагрузки в 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}
Я думаю, что это поведение глубоко укоренилось в спецификации 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')
там, где это необходимо.
unsafe
и safe
загрузчики реализуют все это (и небезопасный также для конкретных языков, что делает его небезопасным). У вас также есть BaseLoader, который превращает все в строку. Поэтому я не уверен, что правильно написать, что это «глубоко укоренено в спецификации YAML».
BaseLoader
?
yaml_constructors
является переменной класса. В этом случае вам нужноSafeLoader
подклассSafeLoader
и использовать его.add_constructor
для всех элементов, кромеtimestamp