2015-02-17 29 views
10

Mam plik some.yaml z poniższą zawartością.Jak zaktualizować plik yaml przy użyciu pythona

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

Plik yaml powinien zostać przeanalizowany i zaktualizowany jak poniżej.

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

Jak przeanalizować wartości i odpowiednio je zaktualizować?

+0

Jeśli używasz [PyYaml] (http://pyyaml.org/wiki/PyYAMLDocumentation), można używać ładowarki do ładowania d ata i Dumper, aby zapisać dane do pliku. Załadowane dane są zwykłym słownikiem w Pythonie, dzięki czemu można uzyskać dostęp do elementu za pomocą klawisza, a zatem zmienić go w dowolny sposób. –

+0

Nie jest jasne, czy chcesz mieć silnik szablonów (i błędnie kierują przydatne odpowiedzi, będąc zbyt wąskim), czy po prostu chcesz przeanalizować YAML i zastąpić niektóre wartości ciągów na sparsowanych danych. Bądź bardziej konkretny i wyjaśnij, co możesz osiągnąć i dlaczego. – MariusSiuram

+0

To jest plik. Muszę parsować plik yaml i zastąpić zawartość. – Chetan

Odpowiedz

14

Pakiet ruamel.yaml został specjalnie ulepszony (przeze mnie począwszy od PyYAML)), aby robić tego rodzaju wycieczkę, programować, aktualizować.

Jeśli zaczniesz z (uwaga usunąłem dodatkowe początkowe spacje):

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

i uruchom:

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) 

wyjście będzie:

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

Kolejność mapowania kluczy (host, username i password), styl i komentarze są zachowane bez żadnych dalszych konkretnych działań.

Zamiast tiret tiret i sekwencja blok domyślić, można zrobić bardziej tradycyjne obciążenia i ustaw tiret ceni sobie:

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

Oto przykład przy użyciu PyYaml. Jak rozumiem, masz coś podobnego do szablonu w formacie yaml i musisz zastąpić miejsca w nawiasach ostrych rzeczywistymi wartościami.

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

Plik jest już obecny i muszę go przeanalizować i zaktualizować. – Chetan

5

Oto jak mogę odczytać z powyższego pliku, o którym wspomniałem, przeanalizować i zaktualizować w razie potrzeby.

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

Powinieneś chyba wspomnieć, że powoduje to usunięcie spacji wiodących i nie ma gwarancji zachowania porządku mapowania kluczy (kiedy to uruchomię, otrzymuję 'host',' password', 'username' zamiast' host', 'username ', 'hasło'). – Anthon

3

Nie wiem, czy potrzebujesz YAML. Oprócz używania tagu YAML wydaje się, że nie interesujesz się dokumentem YAML. Dlaczego więc nie używać Jinja2 lub jakiegoś języka szablonów?

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

nie wiem czy to jest dobry pomysł, ale jeśli tylko trzeba uzyskać plik z niektóre pola zmianie, nie trzeba właściwie analizować dokumentu YAML i mogą korzystać z szablonu język bezpośrednio.


Bonus: przypadków użycia

Ja pracowałem z bardzo złożonych dokumentów YAML, na których znajdują się znaczniki nieznany

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

Performing ważnego parse tego dokumentu jest trudne i czas -trawiący. Muszę zapełnić tylko niektóre wartości, a YAML jest wysyłany do aplikacji innej firmy. Dlatego zamiast analizowania pliku YAML lub próby wygenerowania poprawnego dokumentu bezpośrednio za pomocą pyyaml, jest prostszy (bardziej wydajny i mniej podatny na błędy), aby wygenerować go bezpośrednio za pomocą szablonów. Co więcej, języki szablonów mogą być łatwo używane z pętlami do wypełniania pól o dynamicznym rozmiarze.

1

Oto jak generować szablony doker-Crane dev, produkcję , scena, itp ...

  1. mkdir crane_templates
  2. dotykowe crane_templates/startowe .py
  3. dodaj zawartość szablonu z 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. pyton crane_gen.py> wynik. yaml

Odpowiedź zainspirowany @MariusSiuram

Powiązane problemy