2012-03-19 4 views
1

私は構成ファイルのデータに属性を使用できるようにするソリューションを探しています。Pythonで設定ファイルを読み込み、ドット表記(属性)を使って値にアクセスできるようにするにはどうすればいいですか?

私はこのような何かをできるようにしたいと思います:

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

私はConfigParserのは私がconfig['section1']['user']のようにいろいろ書いを行うことができるようになるが、それはあまりにも醜いです、私たちはより良い行うことはできません知っているのですか?

解決方法は、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' 

EDIT:スヴェン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 
関連する問題