source

YAML은 5e-6을 번호가 아닌 문자열로 로드합니다.

manysource 2023. 2. 8. 19:45

YAML은 5e-6을 번호가 아닌 문자열로 로드합니다.

YAML이 있는 JSON 덤프를 통해 e로 번호를 로드하면 번호가 플로트가 아닌 문자열로 로드됩니다.

나는 이 간단한 예가 나의 문제를 설명할 수 있다고 생각한다.

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 규격은 과학적 표기법의 정규식을 다음과 같이 지정합니다.

-? [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 사양의 regex 사이에 불일치가 있습니다(숫자 내의 필수 닷과 관련된 것).e(소문자일 것.JSON 규격은 'e/E' 앞에 점을 찍지 않아도 되고 'e/E' 뒤에 부호를 붙이지 않아도 된다는 점에서 IMO가 매우 명확합니다.

여기에 이미지 설명 입력

PyYAML 실장은 부분적으로 JSON 사양에 따라 플로팅되고 부분적으로 regex에 대해 매칭되며 유효해야 할 번호로 실패합니다.

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은 이 숫자도 문자열로 간주합니다.

그런 것 같아요

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을 처음 사용하기 때문에 어떤 것이 가장 좋은지 모르겠습니다만, 쓰는 것도 마찬가지입니다.

1.0e-1

또는

1.0E-1

바로 사용할 수 있게 되었습니다.즉, 계수를 사용하여 소수점을 구합니다(소수가 없으면 문자열도 구함).

언급URL : https://stackoverflow.com/questions/30458977/yaml-loads-5e-6-as-string-and-not-a-number