在YAML中设置数据类型

时间:2019-01-18 17:30:05

标签: python python-3.x yaml

我在YAML中有一个配置文件,其中包含字符串,浮点数,整数和列表。我想在加载YAML时返回该列表一个numpy数组。因此,例如,如果YAML如下:

name: 'John Doe'
age: 20
score:
  -- 19
   - 45
  -- 21
   - 12
  -- 32
   - 13

我读的是

import yaml

def read(CONFIG_FILE):
    with open(CONFIG_FILE) as c:
        return yaml.load(c)

config = read('path\to\yml')

然后我想要config['score']而不是list键入为numpy.array。当然,可以在YAML之外使用numpy.array(config['score'])之类的方法轻松完成此操作,但我想避免这种情况。

我尝试按照文档(https://pyyaml.org/wiki/PyYAMLDocumentation)中的说明设置标签,但无法使其正常工作。因此,例如,以下操作失败:

score:!!python/object:numpy.array
  -- 19
   - 45
  -- 21
   - 12
  -- 32
   - 13

将标签更改为!!python/module:numpy.array!!python/name:numpy.array也不起作用。

我该如何进行这项工作?我正在使用Python v.3

1 个答案:

答案 0 :(得分:1)

用获取的数据转储一个numpy数组,将获得一个 比仅添加一个复杂的YAML文件要复杂得多 标签。因此,我建议您仅定义自己的标签, 导致数据加载,然后转换为numpy on 苍蝇。这样,您不必遍历生成的加载结构即可找到score或其值。

config.yaml

name: 'John Doe'
age: 20
score: !2darray
  -- 19
   - 45
  -- 21
   - 12
  -- 32
   - 13

您还必须意识到该文件中score的值是简单的多行 标量,它将作为字符串'-- 19 - 45 -- 21 - 12 -- 32 - 13'

加载
import sys
import ruamel.yaml
from pathlib import Path
import numpy

config_file = Path('config.yaml')

yaml = ruamel.yaml.YAML(typ='safe')

@yaml.register_class
class Array:
    yaml_tag = '!2darray'

    @classmethod
    def from_yaml(cls, constructor, node):
        array = []
        for x in node.value.split():
            if x == '--':
                sub_array = []
                array.append(sub_array)
                continue
            if x == '-':
                continue
            sub_array.append(int(x))
        return numpy.array(array)

data = yaml.load(config_file)
print(type(data['score']))
print(data)

给出:

<class 'numpy.ndarray'>
{'name': 'John Doe', 'age': 20, 'score': array([[19, 45],
       [21, 12],
       [32, 13]])}

如果您输入的score的值是序列序列, -后需要一个空格,然后才将其解释为 序列输入指示器:

name: 'John Doe'
age: 20
score: !2darray
  - - 19
    - 45
  - - 21
    - 12
  - - 32
    - 13

如果将其作为输入,则需要调整from_yaml方法:

@yaml.register_class
class Array:
    yaml_tag = '!2darray'

    @classmethod
    def from_yaml(cls, constructor, node):
        array = constructor.construct_sequence(node, deep=True)
        return numpy.array(array)

给出的输出与以前完全相同。