YAML将5e-6加载为字符串而不是数字

Ore*_*ren 18 python json dictionary pyyaml

当我使用YAML加载带有e形式的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}
Run Code Online (Sandbox Code Playgroud)

YAML将1e-06加载为字符串而不是数字?我该如何解决?

小智 28

我觉得

1.0e-1
Run Code Online (Sandbox Code Playgroud)

或者

1.0E-1
Run Code Online (Sandbox Code Playgroud)

已经解决了我的问题。我读取yaml文件的代码是这样的

import yaml


def read_config(path: str):
    """read yaml file"""
    with open(path, 'r') as f:
        data = yaml.safe_load(f)
    return data
Run Code Online (Sandbox Code Playgroud)


Ant*_*hon 23

问题在于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.'))
Run Code Online (Sandbox Code Playgroud)

YAML规范将科学记数法的正则表达式指定为:

-? [1-9] ( \. [0-9]* [1-9] )? ( e [-+] [1-9] [0-9]* )?
Run Code Online (Sandbox Code Playgroud)

后者使点可选,这不是上述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
Run Code Online (Sandbox Code Playgroud)

结果是:

data {'low': 1e-06, 'one': 1}
Run Code Online (Sandbox Code Playgroud)

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(All)

data = ruamel.yaml.load(jAll)
print 'data', data
Run Code Online (Sandbox Code Playgroud)

输出:

data {'low': 1e-06, 'one': 1}
Run Code Online (Sandbox Code Playgroud)

ruamel.yaml也接受数字'1.0e6',PyYAML也将其视为一个字符串.

  • @MarkAmery我去年为PyYAML提交了一个PR,它重新整合了两个代码分支(Python2和Python3)而没有任何形式的反应该项目目前最好是hybernating而且我不会浪费我的时间在PyYAML的PR上直到它重新唤醒.我后来分道扬and并继续修复(在PyYAML上还有一些突出的东西),因为我不得不前进而不能再等了.我认为这是一个错误,因为它没有实现YAML是JSON超集的原则,也没有实现YAML规范中给出的确切正则表达式.通过此更改,我尝试时所有现有的PyYAML单元测试都通过了. (3认同)
  • 如果我理解正确,从客观上来说这是PyYAML中的错误吗?您是否提交了修复请求的拉动请求? (2认同)

Fra*_*o C 13

我刚开始使用 YAML,所以不知道什么是最好的,但可以写

1.0e-1
Run Code Online (Sandbox Code Playgroud)

或者

1.0E-1
Run Code Online (Sandbox Code Playgroud)

在我的 YAML 文件中,它可以开箱即用。也就是说,有一个带有系数的小数(没有小数,我也得到了字符串)。