2014-06-25 21 views
5

Ho un progetto python in cui mi piacerebbe utilizzare YAML (pyYaml 3.11), in particolare perché è "carino" e facile da modificare in un editor di testo se e quando necessario. Il mio problema, però, è che se porto lo YAML in un'applicazione python (come avrò bisogno di farlo) e modifichi il contenuto (come avrò bisogno di farlo), allora la scrittura del nuovo documento in genere non è così carina come quello che ho iniziato.pretty output with pyyaml ​​

La documentazione pyyaml ​​è piuttosto scarsa - non documenta nemmeno i parametri della funzione dump. Ho trovato http://dpinte.wordpress.com/2008/10/31/pyaml-dump-option/. Tuttavia, mi mancano ancora le informazioni di cui ho bisogno. (Ho iniziato a guardare la fonte, ma non sembra la più invitante Se non trovo la soluzione qui, allora è la mia unica risorsa.)

Inizio con un documento simile al seguente:

 
- color green : 
    inputs : 
     - port thing : 
      widget-hint : filename 
      widget-help : Select a filename 
     - port target_path : 
      widget-hint : path 
      value : 'thing' 
    outputs: 
     - port value: 
      widget-hint : string 
    text : | 
      I'm lost and I'm found 
      and I'm hungry like the wolf. 

Dopo aver caricato in python (yaml.safe_load (s)), provo un paio di modi delle pratiche di dumping fuori:

 
>>> print yaml.dump(d3, default_flow_style=False, default_style='') 
- color green: 
    inputs: 
    - port thing: 
     widget-help: Select a filename 
     widget-hint: filename 
    - port target_path: 
     value: thing 
     widget-hint: path 
    outputs: 
    - port value: 
     widget-hint: string 
    text: 'I''m lost and I''m found 

     and I''m hungry like the wolf. 

     '
 
>>> print yaml.dump(d3, default_flow_style=False, default_style='|') 
- "color green": 
    "inputs": 
    - "port thing": 
     "widget-help": |- 
      Select a filename 
     "widget-hint": |- 
      filename 
    - "port target_path": 
     "value": |- 
      thing 
     "widget-hint": |- 
      path 
    "outputs": 
    - "port value": 
     "widget-hint": |- 
      string 
    "text": | 
     I'm lost and I'm found 
     and I'm hungry like the wolf. 

Idealmente, vorrei "corte" a stringhe non usare le virgolette, come nel primo risultato. Ma vorrei che le stringhe multi-linea fossero scritte come blocchi, come nel caso del secondo risultato. Credo che fondamentalmente, sto cercando di minimizzare un'esplosione di citazioni inutili nel file che ritengo renderebbe molto più noioso modificare in un editor di testo.

Qualcuno ha qualche esperienza con questo?

risposta

5

se è possibile utilizzare ruamel.yaml (disclaimer: io sono l'autore di questa versione migliorata di PyYAML) si può fare:

import ruamel.yaml 

yaml_str = """\ 
- color green : 
    inputs : 
     - port thing : 
      widget-hint : filename 
      widget-help : Select a filename 
     - port target_path : 
      widget-hint : path 
      value : 'thing' 
    outputs: 
     - port value: 
      widget-hint : string 
    text : | 
      I'm lost and I'm found 
      and I'm hungry like the wolf. 
""" 

data = ruamel.yaml.round_trip_load(yaml_str) 
res = "" 
for line in ruamel.yaml.round_trip_dump(data, indent=5, block_seq_indent=3).splitlines(True): 
    res += line[3:] 
print(res) 

si ottiene:

- color green: 
     inputs: 
      - port thing: 
       widget-hint: filename 
       widget-help: Select a filename 
      - port target_path: 
       widget-hint: path 
       value: thing 
     outputs: 
      - port value: 
       widget-hint: string 
     text: | 
      I'm lost and I'm found 
      and I'm hungry like the wolf. 

Non è esattamente quello che hai fatto iniziare con (ma dopo questo round-trip è stabile). Con versioni più recenti di ruamel.yaml puoi impostare sia il rientro che il relativo rientro di una sequenza - all'interno di quel trattino. Quest'ultima tuttavia influenza anche la sequenza di livello superiore, quindi l'elaborazione post.

importante (per me) le cose che si conservano: i commenti, le ancore, mappatura fonde, e scalari letterali (multilinea utilizzando |)

+0

@AndySmith Ok. Rimuoviamo questi commenti perché non aiuteranno nessuno. – Anthon

+0

È facile specificare in ruamel.yaml che le stringhe su più righe dovrebbero essere scritte come blocchi (con '|') e la stringa breve non dovrebbe ricevere virgolette, senza avere già un file yaml per invocare un round-trip? – oulenz

+0

@oulenz Questo dipende dalla tua definizione di facile, tu ovviamente devi avere delle regole (ad esempio qualsiasi stringa che contiene una nuova riga dovrebbe essere un blocco letterale scalare, tutti gli spazi senza dovrebbero essere non quotati) se non vuoi usarli a mano. Perché non fai una domanda qui su SO su questo, se sei interessato a farlo? – Anthon

3

Prova la bella stampante pyaml. Esso si avvicina, anche se non le virgolette attorno brevi stringhe messo con spazi in loro:

>>> print pyaml.dump(d3) 
- 'color green': 
    inputs: 
     - 'port thing': 
      widget-help: 'Select a filename' 
      widget-hint: filename 
     - 'port target_path': 
      value: thing 
      widget-hint: path 
    outputs: 
     - 'port value': 
      widget-hint: string 
    text: | 
     I'm lost and I'm found 
     and I'm hungry like the wolf.