число загрузки pyyaml ​​в виде десятичного числа

yaml.load загружает числа, поскольку Python плавает. Я не могу найти простой способ переопределить это.

Сравните json.load, который позволяет parse_float=Decimal, если вы хотите анализировать числа с плавающей запятой как decimal.Decimals.

Есть ли способ сделать это с помощью PyYAML? Или это не рекомендуется из-за какого-то свойства спецификации YAML?


person jsharp    schedule 16.11.2017    source источник


Ответы (1)


Вы можете сделать что-то вроде:

def decimal_constructor(loader, node):
    value = loader.construct_scalar(node)
    return Decimal(value)

yaml.add_constructor(u'!decimal', decimal_constructor)

Это позволяет загружать десятичные числа, но только, если они имеют префикс с тегом !decimal в документе YAML. Однако вы можете использовать пользовательский Resolver для преобразования всех чисел в !decimal:

class MyResolver(BaseResolver):
    pass

MyResolver.add_implicit_resolver(
        '!decimal',
        re.compile(r'''^(?:[-+]?(?:[0-9][0-9_]*)\.[0-9_]*(?:[eE][-+][0-9]+)?
                    |\.[0-9_]+(?:[eE][-+][0-9]+)?
                    |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]*
                    |[-+]?\.(?:inf|Inf|INF)
                    |\.(?:nan|NaN|NAN))$''', re.X),
        list('-+0123456789.'))

Вам следует скопировать другие неявные преобразователи из преобразователя по умолчанию< /а>. Затем вам нужно определить Loader, который использует ваш преобразователь.

class MyLoader(Reader, Scanner, Parser, Composer, SafeConstructor, MyResolver):
    def __init__(self, stream):
        Reader.__init__(self, stream)
        Scanner.__init__(self)
        Parser.__init__(self)
        Composer.__init__(self)
        SafeConstructor.__init__(self)
        MyResolver.__init__(self)

Выше мы добавили ваш конструктор в загрузчик по умолчанию. Измените эту строку на:

yaml.add_constructor(u'!decimal', decimal_constructor, MyLoader)

Наконец, загрузите YAML, используя

yaml.load(stream, MyLoader)
person flyx    schedule 17.11.2017