2012-03-19 9 views
1

나는 구성 파일 데이터에 대한 속성을 사용할 수있는 솔루션을 찾고 있습니다.파이썬에서 구성 파일을로드하고 점 표기 (속성)를 사용하여 값에 액세스하는 방법은 무엇입니까?

나는 이런 식으로 뭔가를 할 수 있도록하고 싶습니다 :

config = Config('config.ini') 
print config.section1.user 
print config.section2.password 

을 나는 ConfigParser 날 config['section1']['user'] 같이가 someting을 할 수 있도록 것이라고 알고 있지만 너무 추한, 우리가 더 잘 할 수없는 이유는 무엇입니까?

솔루션은 Python 2.5 이상에서 작동해야합니다.

+2

어떻게 당신이'ConfigParser'의 모든 일반적인 특성을 액세스 할 것인가? 'options','read','get','write'와 같은 이름을 가진 꽤 많은 것들이 있습니다. 이러한 속성들의 네임 스페이스를 설정 파일의 네임 스페이스와 혼합하는 것은 나쁜 생각입니다. 어쨌든이 작업을 수행하고 충돌을 해결하려는 방법을 자세히 확인하면 작업 수행 방법을 알려줄 수도 있습니다. 그리 어렵지는 않습니다. 단지 나쁜 생각 일뿐입니다. –

+1

[변수 이름에서 데이터를 지키십시오.] (http://nedbatchelder.com/blog/201112/keep_data_out_of_your_variable_names.html) – katrielalex

+0

@SvenMarnach : 당신은 속성에 대해 완전히 정확합니다. 나는 그들을 잊어 버리고 해결책을 게시했습니다. 따라서 문제는 속성을 사용하여 액세스 할 수없는 일부 구성 옵션을 만들 수있는 가능한 이름 충돌이기도합니다. – Tadeck

답변

1

그것은 못생긴 것이 아닙니다. 점 표기법은 '다른 사용자 정의 클래스'객체의 일부 사용자 정의 클래스가 있음을 의미합니다. 더 실현 가능한 방법은 사전 (괄호 표기법 사용)을 사용하는 것입니다.

그러나 당신이 주장하는 경우, 당신은 아마 그런 식으로 코드 변환 할 수 있습니다 :

>>> c1 = { 
    'conf1': { 
     'key1': 'aaa', 
     'key2': 12321, 
     'key3': False, 
     }, 
    'conf2': 'bbbb', 
    } 
>>> c1 
{'conf2': 'bbbb', 'conf1': {'key3': False, 'key2': 12321, 'key1': 'aaa'}} 
>>> c2 = config2object(c1) 
>>> c2.conf1 
{'key3': False, 'key2': 12321, 'key1': 'aaa'} 
>>> c2.conf1.key1 
'aaa' 
>>> c2.conf1.key3 
False 
>>> c2.conf2 
'bbbb' 

편집 : 스벤 Marnach이 Config('config.ini')가 주목

def config2object(config): 
    """ 
    Convert dictionary into instance allowing access to dictionary keys using 
    dot notation (attributes). 
    """ 
    class ConfigObject(dict): 
     """ 
     Represents configuration options' group, works like a dict 
     """ 
     def __init__(self, *args, **kwargs): 
      dict.__init__(self, *args, **kwargs) 
     def __getattr__(self, name): 
      return self[name] 
     def __setattr__(self, name, val): 
      self[name] = val 
    if isinstance(config, dict): 
     result = ConfigObject() 
     for key in config: 
      result[key] = config2object(config[key]) 
     return result 
    else: 
     return config 

그리고 테스트가 예상 결과를 보여를 일부 사용자 정의 클래스 인스턴스. 사전이 아니기 때문에 매우 유용 할 수있는 몇 가지 사용자 지정 메서드가 있지만 이름 충돌이있는 경우 일부 구성 옵션을 액세스 할 수 없게 만들 수 있습니다. 따라서 선호하는 방법은 앞서 언급 한 솔루션을 사용하는 것이 아니라 구성 옵션에 액세스 할 때 괄호 표기법을 사용하는 것입니다.

0

도트 표기법을 사용하여 ConfigParser가 구성 파일에서 읽은 속성에 액세스하고 싶었습니다. (Available on github). 여기

는 ConfigParser을 확장 할 내 시도 :

from ConfigParser import ConfigParser as BaseClass 

SPACE = " " 
UNDERSCORE = "_" 


def internal_name(name, needle=SPACE, replacement=UNDERSCORE): 
    return name.replace(needle, replacement) 


def reverse_name_internalization(name): 
    return internal_name(name, needle=UNDERSCORE, replacement=SPACE) 


class DotNotationConfigParser(BaseClass, object): 

    def __init__(self, coersion_map=None, *args, **kwargs): 
     super(DotNotationConfigParser, self).__init__(*args, **kwargs) 

     self.optionxform = internal_name 
     self.section_attr = None 

    def get_internalized_section(self, section): 
     if self.has_section(section): 
      return internal_name(section) 

    def __set_section_obj(self, internalized_section): 
     if self.has_section(internalized_section): 
      section = internalized_section 
     else: 
      section = reverse_name_internalization(internalized_section) 

     if self.get_internalized_section(section): 
      # set an attr to an object instance with section items 
      obj = type('',(), dict(self.items(section)))() 
      setattr(self, internalized_section, obj) 

    def __getattr__(self, attr): 
     try: 
      return super(DotNotationConfigParser, self).__getattribute__(attr) 
     except AttributeError: 
      section = attr 
      self.__set_section_obj(section) 
      return super(DotNotationConfigParser, self).__getattribute__(attr) 


try: 
    from cStringIO import StringIO 
except ImportError: 
    from StringIO import StringIO 
configuration_file = """ 
[section 1] 
foo = the foo value 
bar = the bar value 
[section 2] 
index = 3 
repeat = False 
[section_n] 
string = This is some text. 
ip = 10.0.1.1 
""" 
configuration_file = StringIO(configuration_file) 

parser = DotNotationConfigParser() 
parser.readfp(configuration_file) 

assert parser.section_1.foo == 'the foo value' 
assert parser.section_1.bar == 'the bar value' 
assert type(parser.section_2.index) is not int 
for section_name in ('section_1', 'section_2', 'section_n'): 
    section = getattr(parser, section_name) 
    options = [option for option in dir(section) 
       if not option.startswith('__')] 
    for option in options: 
     print section_name, ": ", getattr(section, option) 

print "dot notation", parser.section_1.foo