2012-06-15 13 views
6

मैं एक YAML config कि तरह दिखता है:एक pyYAML फ़ाइल कैसे लोड करें और शब्दकोश नोटेशन का उपयोग करने के बजाय विशेषताओं का उपयोग करके इसे एक्सेस करें?

config: 
- id: foo 
- name: bar 
content: 
- run: xxx 
- remove: yyy 

मैं इसे लोड करने के लिए अजगर YAML मॉड्यूल का उपयोग कर रहा है, लेकिन मैं की तरह बेहतर तरीके से उपयोग करना चाहते:

stream = open(filename) 
config = load(stream, Loader=Loader) 
print(config['content']) 

मैं क्या चाहते करने के लिए है करने में सक्षम हो: print(config.content)

+1

http://stackoverflow.com/questions/2352181/how-to-use-a-dot-to-access-members-of-dictionary – Justin

+0

@ जस्टिन का डुप्लिकेट: यह इस प्रश्न का डुप्लिकेट नहीं है, क्योंकि आप 'dict' के उदाहरणों की बजाय इच्छित वर्ग की वस्तुओं को बनाने के लिए YAML लोडर को आसानी से पैच कर सकते हैं। –

उत्तर

5

आप के रूप this जवाब में चर्चा की, निम्नलिखित वर्ग का उपयोग कर शब्दकोशों के साथ वस्तु संकेतन का उपयोग कर सकते हैं:

class DictAsMember(dict): 
    def __getattr__(self, name): 
     value = self[name] 
     if isinstance(value, dict): 
      value = DictAsMember(value) 
     return value 

कार्रवाई में इस वर्ग:

>>> my_dict = DictAsMember(one=1, two=2) 
>>> my_dict 
{'two': 2, 'one': 1} 
>>> my_dict.two 
2 

संपादित यह उप के साथ काम करता है रिकर्सिवली शब्दकोश, उदाहरण के लिए:

>>> my_dict = DictAsMember(one=1, two=2, subdict=dict(three=3, four=4)) 
>>> my_dict.one 
1 
>>> my_dict.subdict 
{'four': 4, 'three': 3} 
>>> my_dict.subdict.four 
4 
+0

मुझे लगता है कि यह पुनरावर्ती रूप से काम नहीं करता है, क्योंकि आप कल्पना कर सकते हैं कि एक ही समस्या कॉन्फ़िगर पेड़ में अन्य प्रविष्टियों के लिए दोहराती है। – sorin

+0

यदि मैं समझता हूं कि आपका क्या मतलब है, यह फिर से काम करता है। क्या मेरा संपादन आपके बिंदु का उत्तर देता है? – Chris

+1

यह क्यों है (वहां का सबसे सरल जवाब) दस लाख बार ऊपर नहीं है? ऐसे दर्जनों समान/डुप्लिकेट प्रश्न हैं जो इस तरह के जटिल तरीके से इसका उत्तर देते हैं! – brandonscript

4

ऐसा करने का सबसे आसान तरीका शायद tag:yaml.org,2002:map के लिए वाईएएमएल कन्स्ट्रक्टर को ओवरराइट करना है, इसलिए यह सामान्य शब्दकोश के बजाय एक कस्टम शब्दकोश कक्षा देता है।

import yaml 

class AttrDict(object): 
    def __init__(self, attr): 
     self._attr = attr 
    def __getattr__(self, attr): 
     try: 
      return self._attr[attr] 
     except KeyError: 
      raise AttributeError 

def construct_map(self, node): 
    # WARNING: This is copy/pasted without understanding! 
    d = {} 
    yield AttrDict(d) 
    d.update(self.construct_mapping(node)) 

# WARNING: We are monkey patching PyYAML, and this will affect other clients!  
yaml.add_constructor('tag:yaml.org,2002:map', construct_map) 

YAML = """ 
config: 
    - id: foo 
    - name: bar 
content: 
    - run: xxx 
    - remove: yyy 
""" 

obj = yaml.load(YAML) 

print(obj.config[0].id) # prints foo 

ध्यान दें कि यह प्रक्रिया YAML का उपयोग करता है, अगर यह सब कुछ सामान्य अजगर तरीके से काम करने की उम्मीद में सब कुछ टूट जाएगा। आप एक कस्टम लोडर का उपयोग कर सकते हैं, लेकिन मुझे व्यक्तिगत रूप से PyYAML दस्तावेज़ थोड़ा भूलभुलैया मिलती है, और ऐसा लगता है कि दुष्प्रभाव एक अपवाद के बजाय एक नियम के रूप में वैश्विक और संक्रामक हैं।

आपको चेतावनी दी गई है।

एक विकल्प के रूप में, अगर अपने स्कीमा अपेक्षाकृत स्थिर आप अपने खुद के वर्गों लिख सकते हैं और उन लोगों के लिए deserialize सकता है (जैसे, class Config साथ id और name गुण)। हालांकि, यह शायद अतिरिक्त कोड की लागत के लायक नहीं होगा।

+0

सरलीकृत और इसे https://gist.github.com/ktaragorn/9cf6d368378b0f65a3a0 में सुधार दिया। कोई बंदरगाह नहीं है और यह एक नेस्टेड फैशन में भी काम करता है साथ ही –

+0

@ कार्तिकटी: सरणी के अंदर घोंसले वाले शब्दकोशों के लिए विफल रहता है। –

+0

मैंने उस मामले का उपयोग भी नहीं किया था .. क्या यह अक्सर होता है जब आप कॉन्फ़िगरेशन फ़ाइलों पर विचार कर रहे होते हैं? –

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

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