2012-11-22 8 views
13

Ich erstelle Yaml-Dokumente aus meinen eigenen Python-Objekten mit PyYaml. zum Beispiel mein Objekt: Hinzufügen von Kommentaren zu YAML erstellt mit PyYaml

class MyObj(object): 
    name = "boby" 
    age = 34 

wird:

boby: 
    age: 34 

So weit so gut.

Aber ich habe keine Möglichkeit, programmatisch Hinzufügen von Kommentaren zu dem erzeugten yaml gefunden, so dass es aussehen wird:

boby:  # this is the name 
    age: 34 # in years 

Mit Blick auf PyYaml Dokumentation und auch auf dem Code, fand ich keine Möglichkeit, dies zu tun.

Irgendwelche Vorschläge?

+0

Ich bin mir fast sicher, dass es keine Möglichkeit gibt, dies mit PyYAML zu tun, ohne wesentliche Teile der Bibliothek neu zu schreiben und eine Reihe von Entscheidungen darüber zu treffen, wie man mit Kommentaren umgehen soll. Möchten Sie Kommentare vom Repräsentanten hinzugefügt werden (zB pro Klasse)? Oder per-instance irgendwie (noch härter)? Dies ist etwas bedauerlich, da die Möglichkeit, Kommentare hinzuzufügen, etwas nützlich sein könnte. – cge

+0

Danke @cge. Das Einbehalten von Kommentaren wäre sehr hilfreich, wenn yaml-Dokumente programmatisch verarbeitet werden. –

+0

http://www.dzone.com/snippets/pyyaml-comment-emitter scheint zu verstehen, wie man es mit den Event/Dumper-Schnittstellen macht. Ich habe noch keine Antwort gepostet, weil ich noch nicht bestätigt habe, dass es funktioniert. – kampu

Antwort

4

Sie wahrscheinlich einige Representer für die MyObj Klasse Dumping, wie standardmäßig haben (print(yaml.dump(MyObj()))) mit PyYAML geben Ihnen:

!!python/object:__main__.MyObj {} 

PyYAML kann nur mit den Kommentaren in der gewünschten Ausgabe eines: verwerfen . Wenn Sie diese gewünschte Ausgabe wieder einzulesen würden Sie sich mit einem dict enden, die ein dict ({'boby': {'age': 34}}, würden Sie nicht eine MyObj() Instanz erhalten, weil es keine Tag-Informationen ist)

Die erweiterte Version für PyYAML, die ich entwickelt (ruamel.yaml) kann YAML mit Kommentaren lesen, Kommentare beibehalten und Kommentare beim Dumping schreiben. Wenn Sie Ihre gewünschte Ausgabe lesen, sehen die resultierenden Daten aus wie ein Diktat, das ein Diktat enthält (und handelt), aber in Wirklichkeit gibt es eine komplexere Datenstruktur, die mit den Kommentaren umgehen kann. Sie können diese Struktur jedoch erstellen, wenn Sie von ruamel.yaml aufgefordert werden, eine Instanz von MyObj auszugeben. Wenn Sie die Kommentare zu diesem Zeitpunkt hinzufügen, erhalten Sie die gewünschte Ausgabe.

from __future__ import print_function 

import sys 
import ruamel.yaml 
from ruamel.yaml.comments import CommentedMap 


class MyObj(): 
    name = "boby" 
    age = 34 

    def convert_to_yaml_struct(self): 
     x = CommentedMap() 
     a = CommentedMap() 
     x[data.name] = a 
     x.yaml_add_eol_comment('this is the name', 'boby', 11) 
     a['age'] = data.age 
     a.yaml_add_eol_comment('in years', 'age', 11) 
     return x 

    @staticmethod 
    def yaml_representer(dumper, data, flow_style=False): 
     assert isinstance(dumper, ruamel.yaml.RoundTripDumper) 
     return dumper.represent_dict(data.convert_to_yaml_struct()) 


ruamel.yaml.RoundTripDumper.add_representer(MyObj, MyObj.yaml_representer) 

ruamel.yaml.round_trip_dump(MyObj(), sys.stdout) 

Welche druckt:

boby:  # this is the name 
    age: 34 # in years 

Es gibt keine Notwendigkeit, mit der Erstellung der CommentedMap Instanzen zu warten, bis Sie die MyObj Instanz darstellen wollen. Ich würde z.B. Machen Sie name und age in Eigenschaften, die Werte von/auf dem geeigneten CommentedMap erhalten/setzen. Auf diese Weise können Sie die Kommentare einfacher hinzufügen, bevor die statische Methode yaml_representer aufgerufen wird, um die MyObj Instanz darzustellen.