Установить типы данных в YAML - PullRequest
0 голосов
/ 18 января 2019

У меня есть файл конфигурации в 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'] вместо списка печаталось как 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 голосов
/ 18 января 2019

Сброс массива с данными, которые вы получаете, вы получите значительно более сложный файл YAML, чем то, что вы можете получить, просто добавив тег. Поэтому я рекомендую вам просто определить свой собственный тег, который вызвать данные, как у вас есть, чтобы загрузить, а затем преобразовать в NumPy на муха. Таким образом, вам не придется проходить по полученной загруженной структуре, чтобы найти 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)

Что дает точно такой же вывод, как и раньше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...