Отключить преобразование значения PyYAML

Я только что начал использовать PyYAML для преобразования некоторых данных.

Я просто использую функцию yaml.load, и это было достаточно хорошо для меня, пока я не заметил, что он пытается преобразовать все значения в уникодированную строку, int, даты и т.д.

Это может быть фатальным в моем приложении, есть ли способ избежать этого преобразования? Я хотел бы получить все как строки. Я посмотрел на конструкторы и не смог найти способ отключить это преобразование.

обновление: То, что я получаю от yaml.load, - это OrderedDict, и все выглядит хорошо. единственная проблема заключается в том, что некоторые значения являются строками, а некоторые - int. Я хотел бы иметь все значения как строки. Я не хочу, чтобы pyyaml ​​менял значения для меня.

Ответ 1

Ну, вы можете использовать Loader=yaml.BaseLoader, чтобы оставить все как строку:

>>> x = [[1,2,3], {1:2}]
>>> s = yaml.dump(x)
>>> s
'- [1, 2, 3]\n- {1: 2}\n'
>>> yaml.load(s)
[[1, 2, 3], {1: 2}]
>>> yaml.load(s, Loader=yaml.BaseLoader)
[[u'1', u'2', u'3'], {u'1': u'2'}]

Ответ 2

Вы можете отключить преобразование и сохранить << слияние с каким-то специальным кодом:

import yaml
from yaml.composer import Composer
from yaml.constructor import BaseConstructor, SafeConstructor
from yaml.nodes import MappingNode
from yaml.parser import Parser
from yaml.reader import Reader
from yaml.resolver import Resolver
from yaml.scanner import Scanner

class MyConstructor(BaseConstructor):
    def __init__(self):
        BaseConstructor.__init__(self)

    # not very elegant, but we avoid copy-paste
    flatten_mapping = SafeConstructor.flatten_mapping

    def construct_mapping(self, node, deep=False):
        if isinstance(node, MappingNode):
            self.flatten_mapping(node)
        return super().construct_mapping(node, deep=deep)

class MyLoader(Reader, Scanner, Parser, Composer, MyConstructor, Resolver):
    def __init__(self, stream):
        Reader.__init__(self, stream)
        Scanner.__init__(self)
        Parser.__init__(self)
        Composer.__init__(self)
        MyConstructor.__init__(self)
        Resolver.__init__(self)

Затем:

>>> yaml.load('''
  foo: &ff
    a: 1
  bar: &bb
    b: 2.0
    <<: *ff
  baz:
    c: 3.00
    <<: *bb
  ''', Loader=MyLoader)
{'foo': {'a': '1'}, 'bar': {'a': '1', 'b': '2.0'}, 'baz': {'a': '1', 'b': '2.0', 'c': '3.00'}}