The problem lies in the fact that the YAML Resolver is set up to match floats as follows:
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.'))
whereas the YAML spec specifies the regex for scientific notation as:
-? [1-9] ( \. [0-9]* [1-9] )? ( e [-+] [1-9] [0-9]* )?
后者使点成为可选的,在隐式解析器中,它不在上述re.compile()
个模式中.
The matching of floats can be fixed so it will accept floating point values with an e
/E
but without decimal dot and with exponents without sign (i.e. +
implied):
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
results in:
data {'low': 1e-06, 'one': 1}
JSON允许的数字和YAML 1.2规范中的正则表达式之间存在差异(关于数字中所需的点,e
是小写).
The PyYAML implementation does match floats partially according to the JSON spec and partially against the regex and fails on numbers that should be valid.
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
with output:
data {'low': 1e-06, 'one': 1}
鲁阿迈尔.yaml还接受数字"1.0e6",PyYAML也将其视为字符串.