YAML将5e-6作为字符串加载,而不是数字 [英] YAML loads 5e-6 as string and not a number

查看:342
本文介绍了YAML将5e-6作为字符串加载,而不是数字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



当我使用YAML加载一个带有形式的JSON转储的数字时,数字将以字符串的形式加载,而不是浮点数。解释我的问题。

  import json 
import yaml

在[1]中:import json

在[2]中:import yaml

在[3]中:All = {'one':1,'low':0.000001}

在[4]中:jAll = json.dumps(全部)

在[5]中:yAll = yaml.safe_load(jAll)

在[6]中:yAll
输出[6]:{'low':'1e-06','one':1}

YAML将 1e-06 加载为字符串而不是数字?如何修复?

解决方案

问题在于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),
列表(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

全= 'one':1,'low':0.000001}

jAll = json.dumps(全部)

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 _] +(? ] [ - +] [0-9] +)?
| [ - +]?[0-9] [0-9 _] *(?:: [0-5]?[0-9]) + \\。[0-9 _] *
| [ - +]?\\。(?: inf | Inf | INF)
| \\。 | NaN | NAN))$''',re.X),
列表(u' - + 0123456789。'))

data = yaml.load(jAll,Loader = loader)
打印'data',数据

结果:

  data {'低':1e-06,'one':1} 

JSON允许的数字和YAML 1.2规范中的正则表达式(关于数字中所需的点,而 e 为小写)。
JSON规范是IMO非常清楚的,因为它不需要'e / E'也不需要在'e / E'之后有一个符号:





PyYAML实现根据JSON规范部分匹配浮点数,部分与正则表达式匹配,并且数字将失败



ruamel.yaml (这是我的增强版本的PyYAML),有这些更新的模式和正常工作:

  import ruamel.yaml 
import json

All = {'one':1,'low':0.000001}

jAll = json.dumps(全部)

data = ruamel.yaml.load(jAll)
打印'data',数据

输出:

  data {'low':1e-06,'one':1} 

ruamel.yaml也接受数字1.0e6,PyYAML也看作一个字符串。


When I load a number with e form a JSON dump with YAML, the number is loaded as a string and not a float.

I think this simple example can explain my problem.

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 loads 1e-06 as a string and not as a number? How can I fix it?

解决方案

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]* )?

the latter makes the dot optional, which it isn't the above re.compile() pattern.

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}

There is discrepancy between what JSON allows in numbers and the regex in the YAML 1.2 spec (concerning the required dot in the number and e being lower case). The JSON specification is IMO very clear in that it doesn't require the dot before 'e/E' nor that is requires a sign after the 'e/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 (which is my enhanced version of PyYAML), has these updated pattern and works correctly:

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}

ruamel.yaml also accepts the number '1.0e6', which PyYAML also sees as a string.

这篇关于YAML将5e-6作为字符串加载,而不是数字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆