Разбор файла yaml и получение словаря - PullRequest
0 голосов
/ 22 мая 2018

Я хотел бы иметь возможность взять YAML, определенный ниже, и превратить его в словарь.

development:
    user:dev_uid
    pass:dev_pwd
    host:127.0.0.1
    database:dev_db

production:
    user:uid
    pass:pwd
    host:127.0.0.2
    database:db

Я смог использовать библиотеку YAML для загрузки данных. Однако мойсловарь содержит элементы окружения в виде длинной строки.

Этот код:

#!/usr/bin/python3

import yaml

config  = yaml.load(open('database.conf', 'r'))

print(config['development'])

дает следующий вывод.

user:dev_uid pass:dev_pwd host:127.0.0.1 database:dev_db

Я не могу получить доступ ни к одномузаписей по имени ключа или загрузите эту строку после использования метода yaml.load.

print(config['development']['user'])

Этот код выдает следующую ошибку:

TypeError: string indices must be integers

В идеале я хотел бы получить функцию синтаксического анализа, которая возвращает словарь или list, чтобы я мог получить доступ ксвойства по имени ключа или с помощью оператора dot, например:

print(config['development']['user'])
config.user

Где я ошибаюсь?

Ответы [ 3 ]

0 голосов
/ 22 мая 2018

Поскольку вы не сразу получаете то, что хотите, с модулем yaml, ваш файл .conf, вероятно, использует формат, отличный от того, который ожидает модуль yaml.

Этот код является быстрымОбходной путь, который дает вам нужный словарь:

for mainkey in ['production','development']:
    d = {}
    for item in config[mainkey].split():
        key,value = item.split(':')
        d[key] = value
    config[mainkey] = d
0 голосов
/ 22 мая 2018

Ваш YAML абсолютно действителен, поэтому при загрузке вы не получите сообщение об ошибке.Он загружается не так, как вы ожидаете, потому что в YAML есть функция для переноса (длинных) строк в пробелах, и это работает для не цитируемых скаляров, таких как

user:dev_uid
pass:dev_pwd
host:127.0.0.1
database:dev_db

Ваш файл YAML эквивалентен:

разработка: "пользователь: dev_uid pass: dev_pwd хост: 127.0.0.1 база данных: dev_db" production: "пользователь: uid pass: pwd host: 127.0.0.2 база данных: db"

и

разработка: пользователь: dev_uid pass: dev_pwd хост: 127.0.0.1 база данных: dev_db производство: пользователь: uid pass: pwd host: 127.0.0.2 база данных: db

, поскольку кавычки не нужны, посколькуне может быть никакой путаницы относительно значения для development, которое будет отображением, так как для этого двоеточие после ключа должно сопровождаться пробелом.Это видно из более старой (ныне устаревшей) спецификации YAML 1.1 , которая использовалась для реализации PyYAML¹.

Лучше всего конвертировать, исправлять YAML, что можно легко сделать, если предположить,что ни один из ключей и значений не имеет встроенных пробелов:

import sys
import yaml


yaml_str = """\
development:
    user:dev_uid
    pass:dev_pwd
    host:127.0.0.1
    database:dev_db

production:
    user:uid
    pass:pwd
    host:127.0.0.2
    database:db
"""

data = yaml.safe_load(yaml_str)
for key in data:
    val = data[key]
    if ':' not in val:
        continue
    data[key] = tmp = {}
    for x in val.split():
        x = x.split(':', 1)
        tmp[x[0]] = x[1]

yaml.safe_dump(data, sys.stdout, default_flow_style=False)

Если ваш файл более сложный, чем тот, который вы представили, вам, возможно, придется возвращаться к значениям dict и элементам списка, что довольно тривиально.

Вышеуказанные выходы:

development:
  database: dev_db
  host: 127.0.0.1
  pass: dev_pwd
  user: dev_uid
production:
  database: db
  host: 127.0.0.2
  pass: pwd
  user: uid

, которые затем загружаются, как вы ожидаете, без хлопот.


¹ Более новый YAML 1.2 допускает пары ключ-значение безпробел после двоеточия при использовании отображений в стиле потока.Но предварительным условием для этого является то, что и ключ, и значение (двойные) заключаются в кавычки.Это изменение было необходимо для обеспечения совместимости YAML 1.2 с JSON:

development: {
    "user":"dev_uid",
    "pass":"dev_pwd",
    "host":"127.0.0.1",
    "database":"dev_db"
  }

0 голосов
/ 22 мая 2018

Ваш "yaml" - это не отображение отображений, это отображение строк.В YAML 1.2 элементам отображения блоков необходимо использовать пробел после разделителя , например

development:
    user: dev_uid
    pass: dev_pwd
    host: 127.0.0.1
    database: dev_db

production:
    user: uid
    pass: pwd
    host: 127.0.0.2
    database: db

Не пытайтесь предварительно обрабатывать этот текст.Вместо этого найдите, кто сгенерировал разметку, и добавьте в них спецификацию .

...