2015-06-23 12 views
6

मैं https://pypi.python.org/pypi/ruamel.yamlमैं कैसे पायथन

कोड का उपयोग कर एक YAML फ़ाइल लिख रहा हूँ में एक YAML फ़ाइल के लिए एक टिप्पणी जोड़ सकते हैं इस तरह है:

import ruamel.yaml 
from ruamel.yaml.comments import CommentedSeq 

d = {} 
for m in ['B1', 'B2', 'B3']: 
    d2 = {} 
    for f in ['A1', 'A2', 'A3']: 
     d2[f] = CommentedSeq(['test', 'test2']) 
     if f != 'A2': 
      d2[f].fa.set_flow_style() 
    d[m] = d2 

    with open('test.yml', "w") as f: 
     ruamel.yaml.dump(
      d, f, Dumper=ruamel.yaml.RoundTripDumper, 
      default_flow_style=False, width=50, indent=8) 

मैं बस की तरह शीर्ष पर टिप्पणी जोड़ना चाहते हैं :

# Data for Class A 

वाईएएमएल डेटा से पहले।

उत्तर

3

अपने with ब्लॉक के भीतर, आप कुछ भी आप फ़ाइल करना चाहते हैं लिख सकते हैं। जब से तुम सिर्फ शीर्ष पर एक टिप्पणी की जरूरत है, f.write() के लिए एक कॉल को जोड़ने से पहले आप ruamel फोन:

with open('test.yml', "w") as f: 
    f.write('# Data for Class A\n') 
    ruamel.yaml.dump(
     d, f, Dumper=ruamel.yaml.RoundTripDumper, 
     default_flow_style=False, width=50, indent=8) 
+0

जो आसान था :) – user3214546

1

कि सिद्धांत रूप में संभव है, क्योंकि आप कर सकते हैं राउंड ट्रिप इस तरह के "शुरू-ऑफ-द फ़ाइल" टिप्पणी है, लेकिन यह वर्तमान ruamel.yaml 0.10 में अच्छी तरह से समर्थित नहीं है और निश्चित रूप से नहीं जब "खरोंच से शुरू" (यानी कोई मौजूदा फ़ाइल नहीं बदल रहा है)। नीचे एक अपेक्षाकृत अच्छा समाधान है, लेकिन मैं सबसे पहले एक बदसूरत कामकाज पेश करना चाहता हूं और यह एक कदम-दर-चरण कैसे किया जाए।

बदसूरत:
यह करने के लिए बदसूरत तरह से बस से पहले आप इसे करने के YAML डेटा लिखने फाइल करने के लिए टिप्पणी जोड़ने के लिए है।
डेटा संरचना पर टिप्पणी सम्मिलित करने के लिए है, इसलिए ऊपर हैक आवश्यक नहीं है, तो आपको पहले सुनिश्चित करने की आवश्यकता: कदम द्वारा

f.write('# Data for Class A\n') 

बस से पहले ruamel.yaml.dump(...)

चरण: यह डालने है आपका d डेटा CommentedMap प्रकार है।एक विशेषता comment की जरूरत है कि है

Comment(comment=[None, [CommentToken(value=u'# Data for Class A\n')]], 
    items={}) 
Comment(comment=None, 
    items={}) 

एक Comment: अगर आप c

import ruamel.yaml 
from ruamel.yaml.comments import Comment, CommentedSeq, CommentedMap 

d = CommentedMap()    # <<<<< most important 
for m in ['B1', 'B2', 'B3']: 
    d2 = {} 
    for f in ['A1', 'A2', 'A3']: 
     d2[f] = CommentedSeq(['test', 'test2']) 
     if f != 'A2': 
      d2[f].fa.set_flow_style() 
    d[m] = d2 

yaml_str = ruamel.yaml.dump(d, Dumper=ruamel.yaml.RoundTripDumper, 
          default_flow_style=False, width=50, indent=8) 

assert not hasattr(d, Comment.attrib) # no attribute on the CommentedMap 

comment = 'Data for Class A' 
commented_yaml_str = '# ' + comment + '\n' + yaml_str 
c = ruamel.yaml.load(commented_yaml_str, Loader=ruamel.yaml.RoundTripLoader) 
assert hasattr(c, Comment.attrib) # c has the attribute 
print c.ca       # and this is what it looks like 
print d.ca       # accessing comment attribute creates it empty 
assert hasattr(d, Comment.attrib) # now the CommentedMap has the attribute 

यह प्रिंट में वापस टिप्पणी की YAML लोड करके एक टिप्पणी है कि एक के साथ कि d चर के अंतर की तुलना ईओएल टिप्पणी (हमेशा केवल एक) और पिछली पंक्ति टिप्पणियों की सूची (CommentTokens के रूप में)

एक CommentToken बनाने के लिए आप एक (फर्जी) StartMark कि यह बताती है कि स्तंभ यह शुरू होता है की जरूरत है:

from ruamel.yaml.tokens import CommentToken 

ct = CommentToken('# ' + comment + '\n', start_mark, None) 

पूर्ववर्ती के पहले तत्व के रूप में टोकन असाइन करें:

from ruamel.yaml.error import Mark 
start_mark = Mark(None, None, None, 0, None, None) # column 0 

अब आप टोकन बना सकते हैं अपने CommentedMap पर सूची:

d.ca.comment = [None, [ct]] 
print d.ca # in case you want to check 

आप देता है:

Comment(comment=[None, [CommentToken(value='# Data for Class A\n')]], 
    items={}) 

और अंत में:

print ruamel.yaml.dump(d, Dumper=ruamel.yaml.RoundTripDumper) 

देता है:

# Data for Class A 
B1: 
     A1: [test, test2] 
     A3: [test, test2] 
     A2: 
     - test 
     - test2 
B2: 
     A1: [test, test2] 
     A3: [test, test2] 
     A2: 
     - test 
     - test2 
B3: 
     A1: [test, test2] 
     A3: [test, test2] 
     A2: 
     - test 
     - test2 
बेशक आप c वस्तु बनाने की जरूरत नहीं है के

, यह सिर्फ उदाहरण के लिए है।

क्या आप उपयोग करना चाहिए: पूरी कवायद को कुछ हद तक आसान तुम सिर्फ विवरण और निम्न विधि में पैच के बारे में CommentedBase एक बार करने के लिए भूल सकता है बनाने के लिए:

from ruamel.yaml.comments import CommentedBase 

def set_start_comment(self, comment, indent=0): 
    """overwrites any preceding comment lines on an object 
    expects comment to be without `#` and possible have mutlple lines 
    """ 
    from ruamel.yaml.error import Mark 
    from ruamel.yaml.tokens import CommentToken 
    if self.ca.comment is None: 
     pre_comments = [] 
     self.ca.comment = [None, pre_comments] 
    else: 
     pre_comments = self.ca.comments[1] 
    if comment[-1] == '\n': 
     comment = comment[:-1] # strip final newline if there 
    start_mark = Mark(None, None, None, indent, None, None) 
    for com in comment.split('\n'): 
     pre_comments.append(CommentToken('# ' + com + '\n', start_mark, None)) 

if not hasattr(CommentedBase, 'set_start_comment'): # in case it is there 
    CommentedBase.set_start_comment = set_start_comment 

और फिर बस कार्य करें:

d.set_start_comment('Data for Class A') 
+0

यह काम करने के लिए बहुत काम करता है, सिर्फ 'f.write() 'को कॉल करने के लिए। क्या फायदा है? ऐसा कहा जाता है, ऐसा लगता है कि यह ruamel के एक अंतर्निहित हिस्से के रूप में समझ में आता है, शायद उन्हें एक पुल अनुरोध भेजते हैं? – dimo414

+2

@ dimo414 हां अगर यह केवल फाइल के शीर्ष के लिए है तो यह ओवरहेड है। लेकिन यदि आप इसे डेटा में जोड़ते हैं और फिर किसी सूची में डेटा का उपयोग करते हैं और लिखते हैं कि यह काम करता है। मैं सामान्य रूप से ruamel.yaml में शामिल करने के लिए इसे बाहर करना चाहता था, इसके लिए एक पीआर आवश्यक नहीं है क्योंकि मैं लेखक हूं। तो यह अगले अपडेट में होगा जो मैं पीईपीआई (10.1) पर अपलोड करता हूं। तो मैं केवल अंतिम पंक्ति के उत्तर को कम कर सकता हूं ;-) – Anthon

संबंधित मुद्दे