2015-02-17 4 views
10

У меня есть файл some.yaml с нижеследующим содержимым.Как обновить файл yaml с помощью python

init_config: {} 
    instances: 
     - host: <IP> 
      username: <username> 
      password: <password> 

Файл yaml должен быть проанализирован и обновлен, как показано ниже.

init_config: {} 
    instances: 
     - host: 1.2.3.4 
      username: Username 
      password: Password 

Как я могу проанализировать значения и соответствующим образом обновить их?

+0

Если вы используете [PyYAML] (http://pyyaml.org/wiki/PyYAMLDocumentation), вы можете использовать погрузчик для загрузки д ata и Dumper для записи данных в файл. Загруженные данные являются обычным словарем в Python, поэтому вы можете получить доступ к элементу по ключу и, таким образом, изменить его по своему усмотрению. –

+0

Неясно, хотите ли вы, чтобы механизм шаблонов (и неверно направлял полезные ответы, будучи слишком узкими), или просто хотите разобрать YAML и заменить некоторые строковые значения на анализируемые данные. Будьте более конкретными и объясните, что вам нужно сделать и почему. – MariusSiuram

+0

Это файл. Мне нужно проанализировать файл yaml и заменить его. – Chetan

ответ

14

Пакет ruamel.yaml был специально усовершенствован (от меня, начиная с PyYAML)), чтобы сделать этот вид в оба конца, программный, обновление.

Если начать с (обратите внимание, что я удалил лишние начальные пробелы):

init_config: {} 
instances: 
    - host: <IP>    # update with IP 
     username: <username> # update with user name 
     password: <password> # update with password 

и запуск:

import ruamel.yaml 

file_name = 'input.yml' 
from ruamel.yaml.util import load_yaml_guess_indent 

config, ind, bsi = load_yaml_guess_indent(open(file_name)) 

instances = config['instances'] 
instances[0]['host'] = '1.2.3.4' 
instances[0]['username'] = 'Username' 
instances[0]['password'] = 'Password' 

ruamel.yaml.round_trip_dump(config, open('output.yml', 'w'), 
          indent=ind, block_seq_indent=bsi) 

Выход будет:

init_config: {} 
instances: 
    - host: 1.2.3.4   # update with IP 
     username: Username  # update with user name 
     password: Password  # update with password 

Упорядочение (host, username и password), стиль и комментарии сохранены без каких-либо дополнительных действий.

Вместо того, чтобы отступ и последовательность блоков отступа угадали, вы можете сделать более традиционную нагрузку и установить отступы значения себя:

config = ruamel.yaml.load(open(file_name), ruamel.yaml.RoundTripLoader) 
ind = 6 
bsi = 4 
0

Вот пример с использованием PyYaml. Насколько я понимаю, у вас есть что-то вроде шаблона в формате yaml, и вам нужно заменить места в угловых скобках фактическими значениями.

import yaml 

s = """ 
    init_config: {} 
    instances: 
     - host: <IP> 
      username: <username> 
      password: <password> 
""" 

dict_obj = yaml.load(s) # loads string in internal data structure - dict 
dict_obj['instances'][0]['host'] = 'localhost' # change values 
print yaml.dump(dict_obj) # dumps dict to yaml format back 
+0

Файл уже присутствует, и мне нужно его проанализировать и обновить. – Chetan

5

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

import yaml 

fname = "some.yaml" 

stream = open(fname, 'r') 
data = yaml.load(stream) 

data['instances'][0]['host'] = '1.2.3.4' 
data['instances'][0]['username'] = 'Username' 
data['instances'][0]['password'] = 'Password' 

with open(fname, 'w') as yaml_file: 
    yaml_file.write(yaml.dump(data, default_flow_style=False)) 
+0

Возможно, вы должны упомянуть, что это разделяет ведущие пробелы и не гарантирует сохранения упорядочения ключей сопоставления (когда я запускаю это, я получаю 'host',' password', 'username' вместо' host', 'username ', 'password'). – Anthon

3

Я не знаю, нужен ли вам YAML. Помимо использования тега YAML, кажется, что вы не заинтересованы в документе YAML. Так почему бы не использовать Jinja2 или какой-либо язык шаблонов?

from jinja2 import Template 

tmpl = Template(u'''\ 
    init_config: {} 
    instances: 
     - host: {{ IP }} 
      username: {{ username }} 
      password: {{ password }} 
''') 

print tmpl.render(
    IP=u"1.2.3.4", 
    username=u"Username", 
    password=u"Password" 
) 

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


Бонус: Используйте случай

Я работал с очень сложными YAML документов, для которых есть теги неизвестные

... 
    propertiesIDs: { 1, 2, 3, 4 } 
    globalID: !myapplication.InterfaceID &primitiveID 

replication: !myapplication.replication 
    beginDate: 2012-09-10T20:00:03 
    endDate: 2020-09-10T20:00:04 
    replicant_uuid: 
    ? 17169504-B6AB-11E4-8437-36E258BB2172 
    ? 206B5842-B6AB-11E4-AAC3-36E258BB2172 
... 

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

1

Вот как я генерировать шаблоны докер-крановые для разработчика, производство , сцена, и т.д. ...

  1. MkDir crane_templates
  2. сенсорное crane_templates/Инициализационных .py
  3. содержание шаблона
  4. Добавить с нано crane_templates/some.yaml
  5. Nano crane_gen.py

--- crane_gen.py ---

#!/usr/bin/env python 
from jinja2 import Environment, PackageLoader 

env = Environment(loader=PackageLoader('crane_templates', './')) 
tmpl = env.get_template('crane.yaml.tmpl') 

result = tmpl.render(
    IP=u"1.2.3.4", 
    username=u"Username", 
    password=u"Password" 
) 

5. питон crane_gen.py> результат. YAML

Ответ вдохновленный @MariusSiuram

Смежные вопросы