2015-02-17 12 views
10

Ho un file some.yaml con i seguenti contenuti.Come aggiornare il file yaml usando python

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

Il file yaml deve essere analizzato e aggiornato come di seguito.

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

Come analizzare i valori e aggiornarli in modo appropriato?

+0

Se si utilizza [PyYaml] (http://pyyaml.org/wiki/PyYAMLDocumentation), è possibile utilizzare Loader per caricare d ata e Dumper per scrivere dati su file. I dati caricati sono un normale dizionario in Python, quindi puoi accedere all'elemento per chiave e quindi cambiarlo come desideri. –

+0

Non è chiaro se si desidera un motore di template (e si sta indirizzando male a risposte utili essendo troppo stretti) o semplicemente si vuole analizzare un YAML e sostituire alcuni valori di stringa nei dati analizzati. Sii più specifico e spiega cosa vuoi ottenere e perché. – MariusSiuram

+0

È un file. Ho bisogno di analizzare un file yaml e sostituire i contenuti. – Chetan

risposta

14

Il pacchetto ruamel.yaml è stato appositamente migliorato (da me a partire da PyYAML)) per eseguire questo tipo di aggiornamento programmatico, programmatico.

Se si inizia con (si prega di notare ho rimosso gli spazi iniziali in più):

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

e si esegue:

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) 

L'output sarà:

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

L'ordinamento di chiavi di mappatura (host, username e password), lo stile e i commenti vengono conservati senza ulteriori azioni specifiche.

Invece di avere il trattino e la sequenza di blocchi trattino indovinato, si può fare un carico più tradizionali, e impostare il rientro dei valori da soli:

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

Ecco un esempio utilizzando PyYaml. Come ho capito tu hai qualcosa come modello nel formato yaml, e devi sostituire i posti tra parentesi angolari con valori reali.

+0

Un file è già presente e ho bisogno di analizzarlo e aggiornarlo. – Chetan

5

Ecco come posso leggere dal file sopra menzionato, analizzare e aggiornare secondo necessità.

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

Probabilmente dovresti dire che questo toglie gli spazi iniziali, e non è garantito per preservare l'ordine dei tasti di mappatura (quando eseguo questo ottengo 'host',' password', 'username' invece di' host', 'username ', 'password'). – Anthon

3

Non so se è necessario YAML. A parte l'uso del tag YAML, sembra che tu non abbia alcun interesse nel documento YAML. Quindi, perché non usare Jinja2 o un linguaggio modello?

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

Non so se è una buona idea, ma se avete solo bisogno di ottenere un file con alcuni campi cambiati, non c'è bisogno di analizzare in realtà il documento YAML e possono beneficiare di un modello lingua direttamente.


Bonus: Usa caso

Ho lavorato con i documenti YAML molto complessi, per i quali ci sono tag sconosciuti

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

Esecuzione di un parse valida di questo documento è difficile e richiede tempo -consuming. Devo compilare solo alcuni valori e lo YAML viene inviato a un'applicazione di terze parti. Quindi, invece di analizzare lo YAML o provare a generare un documento valido direttamente usando pyyaml, è più semplice (più efficiente in termini di tempo, meno incline ai bug) per generarlo direttamente attraverso i modelli. Inoltre, i linguaggi template possono essere facilmente utilizzati con loop per popolare campi di dimensioni dinamiche.

1

Ecco come ho generato modelli di finestra mobile-gru per dev, la produzione , stage, ecc ...

  1. mkdir crane_templates
  2. tocco crane_templates/init .py
  3. Aggiungere contenuto modello con 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. pitone crane_gen.py> risultato. YAML

risposta ispirata @MariusSiuram