2015-02-17 4 views
10

Ich habe eine some.yaml Datei mit den folgenden Inhalten.So aktualisieren Sie die YAML-Datei mit Python

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

Die yaml-Datei sollte wie folgt analysiert und aktualisiert werden.

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

Wie parse ich die Werte und aktualisiere sie entsprechend?

+0

Wenn Sie [PyYaml] (http://pyyaml.org/wiki/PyYAMLDocumentation), können Sie Loader verwenden d zu laden Ata und Dumper, um Daten in Datei zu schreiben. Die geladenen Daten sind ein gewöhnliches Wörterbuch in Python, so dass Sie Element für Schlüssel zugreifen und es so ändern können, wie Sie es wünschen. –

+0

Es ist nicht klar, ob Sie eine Template-Engine (und zu viele sinnvolle Antworten, die zu eng sind) verwenden möchten oder einfach nur eine YAML analysieren und die analysierten Daten durch einige String-Werte ersetzen möchten. Seien Sie genauer und erklären Sie, was Sie einfach erreichen und warum. – MariusSiuram

+0

Es ist eine Datei. Ich muss eine YAML-Datei analysieren und den Inhalt ersetzen. – Chetan

Antwort

14

Das ruamel.yaml Paket wurde speziell erweitert (von mir ausgehend von PyYAML)), um diese Art von round-trip, programmatic, update.

Wenn Sie mit starten (bitte beachten Sie entfernte ich die zusätzlichen Anfangs Leerzeichen):

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

und laufen:

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) 

Der Ausgang wird sein:

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

Die Bestellung von Mapping-Tasten (host, username und password), der Stil und werden die Kommentare ohne weitere spezifische Maßnahmen beibehalten.

Statt der Gedankenstrich und Blockfolge indent erraten zu haben, können Sie eine traditionellere Last tun, und stellen Sie die indent Werte selbst:

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

Hier sind Beispiele mit PyYaml. Wie ich verstehe, haben Sie etwas wie Vorlage in yaml Format, und Sie müssen Orte in spitzen Klammern mit tatsächlichen Werten ersetzen.

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

Eine Datei ist bereits vorhanden und ich muss sie analysieren und aktualisieren. – Chetan

5

Dies ist, wie ich von der oben genannten Datei lesen kann ich Parsing und update wie benötigt.

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

Sie sollten wahrscheinlich erwähnen, dass dies die führenden Leerzeichen entfernt, und es ist nicht garantiert, dass die Reihenfolge der Zuordnungsschlüssel erhalten bleibt (wenn ich dies ausführe, bekomme ich 'host',' password', 'username' anstelle von' host', 'username) ', 'Passwort'). – Anthon

3

Ich weiß nicht, ob Sie YAML benötigen. Abgesehen von der Verwendung des YAML-Tags scheint es, dass Sie kein Interesse am YAML-Dokument haben. Warum also nicht Jinja2 oder eine Template-Sprache benutzen?

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" 
) 

Ich weiß nicht, ob es eine gute Idee ist, aber wenn Sie nur eine Datei zu erhalten, müssen mit einigen Bereichen verändert, brauchen Sie nicht wirklich das YAML Dokument zu analysieren und aus einer Vorlage profitieren können Sprache direkt.


Bonus: Use Case

Ich habe mit sehr komplexen YAML Dokumenten gearbeitet, für die es Tags unbekannt

... 
    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 
... 

einen gültigen Parse dieses Dokuments Performing ist schwierig und zeit -konsumierend. Ich muss nur einige Werte auffüllen, und der YAML wird an eine Anwendung von Drittanbietern gesendet. Anstatt also das YAML zu analysieren oder zu versuchen, ein gültiges Dokument direkt mit pyyaml ​​zu erzeugen, ist es einfacher (zeiteffizienter, weniger fehleranfällig), es direkt über Templates zu generieren. Darüber hinaus können Vorlagensprachen problemlos mit Loops verwendet werden, um dynamisch große Felder zu füllen.

1

Hier ist, wie ich Docker-Kran-Vorlagen für Entwickler generieren, Produktion , Bühne, etc ...

  1. mkdir crane_templates
  2. Touch crane_templates/init Py
  3. Add Vorlageninhalt mit nano crane_templates/some.yaml
  4. 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. Python crane_gen.py> Ergebnis. yaml

Antwort von @MariusSiuram inspiriert

Verwandte Themen