2012-11-22 123 views
13

我使用PyYaml從我自己的python對象創建Yaml文檔。 例如我的對象: 向PyYaml生成的YAML添加註釋

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

變爲:

boby: 
    age: 34 

到目前爲止好。

但我還沒有發現一種以編程方式添加註釋到生產YAML所以它看起來像:

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

看着PyYaml文檔以及在代碼中,我沒有發現這樣做的方式。

有什麼建議嗎?

+0

我幾乎可以肯定,PyYAML沒有辦法做到這一點,因爲它基本上沒有重新編寫庫的主要部分,並且做出了許多關於如何處理註釋的決定。您是否希望代表(例如,每班)添加意見?或每個實例莫名其妙(甚至更難)?這有點不幸,因爲添加註釋的能力可能有些用處。 – cge

+0

謝謝@cge。以編程方式處理yaml文檔時,保留註釋將非常有幫助。 –

+0

http://www.dzone.com/snippets/pyyaml-comment-emitter似乎明白如何使用Event/Dumper界面來完成它。不發佈作爲答案,因爲我還沒有驗證它的工作。 – kampu

回答

4

你可能有一些申述的MyObj中類,因爲默認情況下傾倒(print(yaml.dump(MyObj())))與PyYAML會給你:

!!python/object:__main__.MyObj {} 

PyYAML只能做一兩件事,在所需輸出的評論:丟棄。如果你會回來讀了所需的輸出,你最終 了包含字典的字典

增強版本PyYAML是我公司開發({'boby': {'age': 34}},因爲沒有標籤信息,你不會得到一個MyObj()實例)( ruamel.yaml)可以在YAML中讀取評論,保存評論並在傾銷時寫評論。 如果你閱讀你想要的輸出結果,結果數據將會看起來像一個包含字典的字典,但實際上有更復雜的數據結構來處理評論。但是,當ruamel.yaml要求您轉儲MyObj的實例時,您可以創建該結構,並且如果您在當時添加註釋,則會獲得所需的輸出。

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) 

它打印:

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

無需等待,直到與你要代表MyObj實例創建CommentedMap實例。我會例如使nameage成爲從適當的CommentedMap獲取/設置值的屬性。這樣,在調用yaml_representer靜態方法來表示MyObj實例之前,您可以更輕鬆地添加註釋。