YAML 加载 5e-6 作为字符串而不是数字
YAML loads 5e-6 as string and not a number
当我使用 YAML 从 JSON 转储中加载一个数字时,该数字被加载为一个字符串而不是一个浮点数。
我想这个简单的例子可以解释我的问题。
import json
import yaml
In [1]: import json
In [2]: import yaml
In [3]: All = {'one':1,'low':0.000001}
In [4]: jAll = json.dumps(All)
In [5]: yAll = yaml.safe_load(jAll)
In [6]: yAll
Out[6]: {'low': '1e-06', 'one': 1}
YAML 加载 1e-06 作为字符串而不是数字?我该如何解决?
问题在于 YAML 解析器设置为匹配浮点数,如下所示:
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 spec 将科学记数法的正则表达式指定为:
-? [1-9] ( \. [0-9]* [1-9] )? ( e [-+] [1-9] [0-9]* )?
后者使点成为可选的,它不在隐式解析器的上述 re.compile()
模式中。
浮点数的匹配可以固定,因此它会接受带有 e
/E
但没有小数点且指数没有符号的浮点值(即隐含 +
) :
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 specification 是 IMO 非常清楚的,因为它不需要 'e/E' 之前的点,也不需要 'e/E':
之后的符号
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 也将其视为字符串。
我是 YAML 的新手,所以不知道什么是最好的,但写其中之一
1.0e-1
或
1.0E-1
在我的 YAML 文件中开箱即用。也就是带系数的有一个小数(没有小数,我也得到了字符串)。
我认为
1.0e-1
或
1.0E-1
解决了我的问题。而我读取yaml文件的代码是这样的
import yaml
def read_config(path: str):
"""read yaml file"""
with open(path, 'r') as f:
data = yaml.safe_load(f)
return data
当我使用 YAML 从 JSON 转储中加载一个数字时,该数字被加载为一个字符串而不是一个浮点数。
我想这个简单的例子可以解释我的问题。
import json
import yaml
In [1]: import json
In [2]: import yaml
In [3]: All = {'one':1,'low':0.000001}
In [4]: jAll = json.dumps(All)
In [5]: yAll = yaml.safe_load(jAll)
In [6]: yAll
Out[6]: {'low': '1e-06', 'one': 1}
YAML 加载 1e-06 作为字符串而不是数字?我该如何解决?
问题在于 YAML 解析器设置为匹配浮点数,如下所示:
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 spec 将科学记数法的正则表达式指定为:
-? [1-9] ( \. [0-9]* [1-9] )? ( e [-+] [1-9] [0-9]* )?
后者使点成为可选的,它不在隐式解析器的上述 re.compile()
模式中。
浮点数的匹配可以固定,因此它会接受带有 e
/E
但没有小数点且指数没有符号的浮点值(即隐含 +
) :
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 specification 是 IMO 非常清楚的,因为它不需要 'e/E' 之前的点,也不需要 'e/E':
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 也将其视为字符串。
我是 YAML 的新手,所以不知道什么是最好的,但写其中之一
1.0e-1
或
1.0E-1
在我的 YAML 文件中开箱即用。也就是带系数的有一个小数(没有小数,我也得到了字符串)。
我认为
1.0e-1
或
1.0E-1
解决了我的问题。而我读取yaml文件的代码是这样的
import yaml
def read_config(path: str):
"""read yaml file"""
with open(path, 'r') as f:
data = yaml.safe_load(f)
return data