2016-02-19 12 views
6

मैं एक ऐसी प्रणाली स्थापित करने की कोशिश कर रहा हूं जहां मेरे पास एक जोड़े (संभवतः अधिक) yaml फ़ाइलें हों जिनका उपयोग कॉन्फ़िगरेशन के लिए किया जाएगा। मैं चीजों को किसी अन्य फाइल में संदर्भित करने में सक्षम होना चाहता हूं।PyYaml दो yaml फ़ाइलों को मिलाकर

मुझे पता है कि वाईएएमएल इसकी अनुमति नहीं देता है।

मेरी योजना, मुझे लगता है कि, दो वाईएएमएल फाइलों को गठबंधन करना है, और फिर इसे एक फ़ाइल के रूप में मानना ​​है। मुझे पूरा यकीन है कि मैं या तो दोनों फाइलों को एक साथ बिल्ली सकता हूं, एक अस्थायी फ़ाइल बना सकता हूं, और उसे एक YAML के रूप में पढ़ सकता हूं, या फ़ाइलों को पाठ के रूप में पढ़ सकता हूं, उन्हें जोड़ सकता हूं और फिर स्ट्रिंग को पार्स कर सकता हूं।

हालांकि, मुझे लगता है कि ऐसा करने का एक बेहतर तरीका होना चाहिए। है?

उत्तर

0

वाईएएमएल में संदर्भ का एकमात्र तरीका & (एंकर) और * (उपनाम) का उपयोग करना है। इन्हें काम करने के लिए उन्हें एक ही वाईएएमएल दस्तावेज में होना होगा। निम्नलिखित काम करेंगे नहीं (इस merge key सुविधा पर आधारित है, लेकिन सामान्य वस्तु संदर्भित ही सीमित है):

import ruamel.yaml 

yaml_str = """\ 
a: &BASE { x: 1, y: 2} 
--- 
b: 
    << : *BASE 
    z: 3 
""" 

for data in ruamel.yaml.load_all(yaml_str): 
    print(data) 

एक संगीतकार त्रुटि है कि "आधार" नहीं मिला है फेंकता है। --- दस्तावेज़ विभाजक को हटाएं और सबकुछ ठीक है।

तो सैद्धांतिक रूप से दो दस्तावेजों को जोड़कर काम कर सकता है। उपनाम के साथ दस्तावेज़ को लोड करना अलग-अलग इसे बिना किसी एंकर के साथ संयोजित किए बिना किया जा सकता है।

अतिरिक्त रूप से चेतावनी यह है कि सभी दस्तावेजों को या तो अपरिवर्तनीय पर मैपिंग या अनुक्रम होना चाहिए। एक मानचित्रण के साथ

- &BASE a 
- b 

:: अगर एक दृश्य गठबंधन होगा

परिणाम लोड करने योग्य नहीं होगा।


के रूप में दर्शाया गया है, यदि उच्चस्तरीय प्रकार सभी फ़ाइलों के लिए ही है, आप YAML फ़ाइलें लोड नहीं कर सकता है और उन्हें स्मृति में गठबंधन। अर्थात।

- &CENTER { x: 1, y: 2 } 
- &LEFT { x: 0, y: 2 } 
- &BIG { r: 10 } 
- &SMALL { r: 1 } 

2.yaml:

# Explicit keys 
- 
    x: 1 
    y: 2 
    r: 10 
    label: center/big 

3.yaml:

# Merge one map 
- 
    << : *CENTER 
    r: 10 
    label: center/big 

4.yaml:

# Merge multiple maps 
- 
    << : [ *CENTER, *BIG ] 
    label: center/big  
012 मर्ज कुंजी प्रलेखन विभाजन में उदाहरण 1.yaml में दिया

5.yaml:

# Override 
- 
    << : [ *BIG, *LEFT, *SMALL ] 
    x: 1 
    label: center/big 

आप व्यक्ति YAML फाइलों पर नहीं उपयोग load() और उन्हें गठबंधन कर सकते हैं:

import ruamel.yaml 
import glob 

data = [] 
for file_name in sorted(glob.glob('*.yaml')): 
    data.append(ruamel.yaml.load(open(file_name))) 
print(ruamel.yaml.dump(data, allow_unicode=True)) 

(ऊपर अगर 2.yaml, आदि जो काम करेगाउपनाम)

नहीं था यदि आप अपने कार्यक्रम से बाहर फ़ाइलों को जोड़ नहीं करना चाहते हैं, तो आप इस वर्ग का उपयोग कर सकते हैं:

class CombinedOpenForReading(object): 
    def __init__(self, file_names): 
     self._to_do = file_names[:] 
     self._fp = None 

    def __enter__(self): 
     return self 

    def __exit__(self, exception_type, exception_value, exception_traceback): 
     if self._fp: 
      self._fp.close() 

    def read(self, size=None): 
     res = '' 
     while True: 
      if self._fp is None: 
       if not self._to_do: 
        return res 
       else: 
        self._fp = open(self._to_do.pop(0)) 
      if size is None: 
       data = self._fp.read() 
      else: 
       data = self._fp.read(size) 
      if size is None or not data: 
       self._fp.close() 
       self._fp = None 
      res += data 
      if size is None: 
       continue 
      size -= len(data) 
      if size == 0: 
       break 
     return res 

करना है:

import ruamel.yaml 
import glob 

with CombinedOpenForReading(sorted(glob.glob('*.yaml'))) as fp: 
    data = ruamel.yaml.round_trip_load(fp) 
assert data[6]['r'] == 10 
print(ruamel.yaml.dump(data, Dumper=ruamel.yaml.RoundTripDumper)) 

प्राप्त करने के लिए:

- &CENTER {x: 1, y: 2} 
- &LEFT {x: 0, y: 2} 
- &BIG {r: 10} 
- &SMALL {r: 1} 
# Explicit keys 
- x: 1 
    y: 2 
    r: 10 
    label: center/big 
# Merge one map 
- <<: *CENTER 
    r: 10 
    label: center/big 
# Merge multiple maps 
- <<: [*CENTER, *BIG] 
    label: center/big 
# Override 
- <<: [*BIG, *LEFT, *SMALL] 
    x: 1 
    label: center/big 

(आपको फ़ाइलों को सही क्रम में सौंपना है, इसलिए तरह। और सुनिश्चित करें कि आपके पास अपनी फ़ाइलों के अंत में नई लाइनें हैं, अन्यथा आपको अप्रत्याशित त्रुटियां मिल सकती हैं।)

+0

अपनी चेतावनी से हाँ का मतलब है कि और आधार और * आधार एक ही तरह की चीज (अनुक्रम बनाम मैपिंग) में होना चाहिए? मुझे एहसास नहीं हुआ कि यह एक समस्या थी, लेकिन यह एक समस्या नहीं होनी चाहिए। मैं एक फ़ाइल में एकाधिक दस्तावेज़ों का उपयोग करने की योजना नहीं बना रहा हूं। मैं एक दस्तावेज़ में एकाधिक फाइलों का उपयोग करने की योजना बना रहा हूं। –

+0

आह, आपका मतलब है कि फ़ाइलों को विलय करने योग्य बनाने के लिए, उनके पास एक ही शीर्ष प्रकार होना चाहिए। हाँ, यह एक समस्या नहीं होनी चाहिए। –

+0

@BrianPostow हां, सबसे ऊपर का प्रकार एक ही – Anthon

0

मुझे लगता है कि यह @ एंथॉन की तुलना में सरल है। यह पूर्ण नहीं हो सकता है, लेकिन मुझे लगता है कि यह सब मुझे चाहिए ...

def merge(fList): 
    ''' 
    Takes a list of yaml files and loads them as a single yaml document. 
    Restrictions: 
    1) None of the files may have a yaml document marker (---) 
    2) All of the files must have the same top-level type (dictionary or list) 
    3) If any pointers cross between files, then the file in which they are defined (&) must be 
    earlier in the list than any uses (*). 
    ''' 

    if not fList: 
     #if flist is the empty list, return an empty list. This is arbitrary, if it turns out that 
     #an empty dictionary is better, we can do something about that. 
     return [] 

    sList = [] 
    for f in fList: 
     with open(f, 'r') as stream: 
      sList.append(stream.read()) 
    fString = '' 
    for s in sList: 
     fString = fString + '\n'+ s 

    y = yaml.load(fString) 

    return y 

टिप्पणियां आपका स्वागत है।

+0

होना चाहिए जो तीन फाइलों को विलय कर रहा है, – holms

+0

विलय करने के बजाए पूरी तरह से कुछ हिस्सों को प्रतिस्थापित करता है? यदि वे शब्दकोश हैं, और चाबियाँ अलग नहीं हैं, तो सुनिश्चित करें, लेकिन शायद यह एक वाईएएमएल त्रुटि है ... –

+0

मुझे ईमानदारी से कोई जानकारी नहीं है। मर्ज-यामल एनपीएम क्ली उपकरण का उपयोग करके समाप्त हो गया। और वहां भी समस्या थी, इसलिए मुझे एक फ़ाइल को दूसरे स्थान पर ले जाना पड़ा: डी यह कैसे संभव है मुझे आश्चर्य है। यहां तक ​​कि yamlreader भी उपलब्ध है जो yaml फ़ाइल सिंटैक्स त्रुटियों की जांच करता है और इसे स्वरूपित करता है, फिर भी मदद नहीं करता है – holms

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