2014-06-25 8 views
5

Ich habe ein Python-Projekt, wo ich YAML (pyYaml 3.11) verwenden möchte, besonders weil es "hübsch" und einfach für Benutzer ist, in einem Texteditor zu bearbeiten, wenn und wenn nötig. Mein Problem ist jedoch, wenn ich das YAML in eine Python-Anwendung bringe (was ich tun muss) und den Inhalt editiere (was ich tun muss), dann ist das Schreiben des neuen Dokuments normalerweise nicht ganz so hübsch wie das, womit ich angefangen habe.hübsche Ausgabe mit pyyaml ​​

Die pyyaml-Dokumentation ist ziemlich schlecht - dokumentiert nicht einmal die Parameter der Dump-Funktion. Ich fand http://dpinte.wordpress.com/2008/10/31/pyaml-dump-option/. Allerdings fehlen mir immer noch die Informationen, die ich brauche. (Ich fing an, die Quelle zu betrachten, aber es scheint nicht die einladendste. Wenn ich hier nicht die Lösung bekomme, dann ist das meine einzige Möglichkeit.)

Ich beginne mit einem Dokument, das so aussieht:

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

Nachdem in python zu laden (yaml.safe_load (n)), versuche ich ein paar Möglichkeiten, um es von Dumping aus:

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

Im Idealfall würde ich "kurze Strings" gerne Verwenden Sie keine Anführungszeichen wie im ersten Ergebnis. Aber ich möchte, dass mehrzeilige Strings als Blöcke geschrieben werden, wie beim zweiten Ergebnis. Ich denke im Grunde genommen versuche ich, eine Explosion von unnötigen Zitaten in der Datei zu minimieren, die ich in einem Texteditor viel ärgerlicher bearbeiten würde.

Hat jemand Erfahrung damit?

Antwort

5

Wenn Sie ruamel.yaml (Disclaimer: Ich bin der Autor dieser erweiterten Version von PyYAML) verwenden, können Sie tun können:

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) 

Sie erhalten:

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

Nicht genau das, was Sie mit haben beginnen (aber nach dieser Rundfahrt ist es stabil). Mit neueren Versionen von ramel.yaml können Sie innerhalb dieses Einzugs sowohl den Einzug als auch den relativen Einzug einer Sequenz - festlegen. Letzteres beeinflusst aber auch Ihre Top-Level-Sequenz, also die Nachbearbeitung.

Wichtig (für mich) Dinge, die erhalten sind: Kommentare, Anker, Mapping verschmilzt und wörtliche Skalare (multi-line mit |)

+0

@AndySmith Ok. Lassen Sie diese Kommentare entfernen, da sie niemandem helfen werden. – Anthon

+0

Ist es in ruamel.yaml einfach zu spezifizieren, dass mehrzeilige Strings als Blöcke geschrieben werden sollen (mit '|') und kurze Strings keine Anführungszeichen erhalten sollen, ohne bereits eine yaml-Datei zu haben, um einen Round-Trip auszulösen? – oulenz

+0

@oulenz Das hängt von Ihrer Definition von easy ab, Sie müssen natürlich entweder einige Regeln haben (zB sollte jeder String, der einen Zeilenumbruch enthält, ein literaler Blockskalar sein; jeder ohne Leerzeichen sollte nicht abgekürzt werden), wenn Sie diese nicht verwenden wollen von Hand. Warum stellst du hier nicht eine Frage an SO, wenn du daran interessiert bist, das zu tun? – Anthon

3

Versuchen Sie die pyaml hübschen Drucker. Es kommt näher, obwohl es in Anführungszeichen kurze Strings mit Leerzeichen in ihnen gesetzt hat:

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