Проблема заключается в том, что YAML Resolver настроен для сопоставления чисел с плавающей запятой следующим образом:
Resolver.add_implicit_resolver(
u'tag:yaml.org,2002:float',
re.compile(u'''^(?:[-+]?(?:[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(u'-+0123456789.'))
тогда как спецификация YAML определяет регулярное выражение для научной записи как:
-? [1-9] ( \. [0-9]* [1-9] )? ( e [-+] [1-9] [0-9]* )?
последнее делает точку необязательной, чего нет в приведенном выше шаблоне re.compile()
в неявном преобразователе.
Сопоставление чисел с плавающей запятой может быть исправлено, поэтому оно будет принимать значения с плавающей запятой с _4 _ / _ 5_, но без десятичной точки и с показателями без знака (т.е. подразумевается +
):
import yaml
import json
import re
All = {'one':1,'low':0.000001}
jAll = json.dumps(All)
loader = yaml.SafeLoader
loader.add_implicit_resolver(
u'tag:yaml.org,2002:float',
re.compile(u'''^(?:
[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+]?[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(u'-+0123456789.'))
data = yaml.load(jAll, Loader=loader)
print 'data', data
приводит к:
data {'low': 1e-06, 'one': 1}
Существует несоответствие между тем, что JSON допускает в числах, и регулярным выражением в спецификации YAML 1.2 (в отношении требуемой точки в числе и e
в нижнем регистре). Спецификация JSON очень ясна ИМО в том, что она не требует точки перед 'e / E' или того, что Требуется знак после "e / E":
![введите описание изображения здесь](https://i.stack.imgur.com/po8A9.gif)
Реализация PyYAML действительно сопоставляет числа с плавающей запятой частично в соответствии со спецификацией JSON и частично с регулярным выражением и не работает с числами, которые должны быть действительными.
ruamel.yaml (это моя расширенная версия PyYAML), имеет этот обновленный шаблон и работает правильно:
import ruamel.yaml
import json
All = {'one':1,'low':0.000001}
jAll = json.dumps(All)
data = ruamel.yaml.load(jAll)
print 'data', data
с выходом:
data {'low': 1e-06, 'one': 1}
ruamel.yaml также принимает число 1.0e6, которое PyYAML также видит как строку.
person
Anthon
schedule
26.05.2015
json.dumps()
, является правильным Номер JSON и AFAICT также правильный номер YAML. PyYAML просто не разбирает его правильно. - person Anthon   schedule 26.05.20151e-3
на1.0e-3
- person Koo   schedule 09.04.2021