2012-06-15 14 views
6

Ben gibi görünen bir YAML yapılandırma vardır: Bunu yüklemek için Python YAML modülünü kullanıyorumPyYAML dosyası nasıl yüklenir ve sözlük notasyonunu kullanmak yerine nitelikler kullanılarak nasıl erişilebilir?

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

fakat bunun daha iyi şekillerde erişmek istiyorum: Ben etmektir istiyorum ne

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

yapmak mümkün: print(config.content).

+1

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

+0

@Justin: Bu sorunun bir kopyası değil. çünkü YAML yükleyicisini, "dict" örneklerinden ziyade, arzu ettiğiniz herhangi bir sınıftaki nesneleri yaratmak için basitçe yamalayabilirsiniz. –

cevap

5
this cevap tartışıldığı gibi, şu sınıfını kullanarak sözlükleri ile nesne gösterimi kullanabilirsiniz

:

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

eylemde Bu sınıf: Bu alt ile yinelemeli çalışır

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

Düzenleme sözlükler, örneğin:

>>> 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

Bence bu, yinelenen çalışmaz, yapılandırma ağacındaki diğer girdiler için aynı sorun tekrarlarını hayal edebileceğiniz gibi düşünüyorum. – sorin

+0

Ne demek istediğimi anlarım, bu yinelemeli olarak çalışır. Düzenlemem senin cevabını mı cevaplıyor? – Chris

+1

Neden bu (buradaki en basit cevap) bir milyon kez tahsis edilmedi? Buna karmaşık bir şekilde cevap veren düzinelerce benzer/yinelenen soru var! – brandonscript

4

Bunu yapmanın en kolay yolu, YAML yapıcısının tag:yaml.org,2002:map için üzerine yazılmasıdır, bu yüzden sıradan bir sözlük yerine özel bir sözlük sınıfı döndürür. Bu da her şey normal Python şekilde çalışması için bekliyorsa, YAML kullanan süreçte başka her şeyi kıracak

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 

Not. Özel bir yükleyici kullanabilirsiniz, ancak PyYAML belgelerini kişisel olarak biraz labirentte buluyorum ve yan etkilerin bir istisna olmaktan ziyade bir kural olarak küresel ve bulaşıcı olduğu görülüyor.

Uyardınız. Bir alternatif olarak

, şema kendi sınıfları yazmak ve olanlara serisini olabilir nispeten durağan ise (örneğin class Configid ve name özelliklere sahip). Ancak, muhtemelen ekstra kodun maliyetine değmez.

+0

Basitleştirilmiş ve bunu https://gist.github.com/ktaragorn/9cf6d368378b0f65a3a0 adresinde geliştirdik. Hiçbir maymun yuvası yoktur ve iç içe geçmiş bir şekilde çalışır. –

+0

@KarthikT: Diziler içinde iç içe geçmiş sözlükler için başarısız. –

+0

Kullanım durumunu dikkate almamıştım bile .. config dosyalarını düşündüğünüzde bu sık sık oluyor mu? –

İlgili konular