2009-05-13 5 views
4

Ich möchte eine INI-Datei als ein Python-Objekt zuordnen. Also, wenn die Datei haben:Wie __setattr__ & __getattr__ für Map-INI-Werte verwenden?

[UserOptions] 
SampleFile = sample.txt 
SamplePort = 80 
SampleInt = 1 
Sample = Aja 
SampleDate = 10/02/2008 

Dann ich will:

c = Configuration('sample.ini') 

c.UserOptions.SamplePort = 90 

Ich bin auf der Suche nach setattr aber ich bekomme einen Rekursionsfehlers. Diese

ist, was ich habe:

class Configuration: 
    def __init__ (self, fileName): 
     cp = SafeConfigParser() 
     cp.read(fileName) 
     self.__parser = cp 
     self.fileName = fileName 

    def __getattr__ (self, name): 
     if name in self.__parser.sections(): 
      return Section(name, self.__parser) 
     else: 
      return None 

    def __str__ (self): 
     p = self.__parser 
     result = [] 
     result.append('<Configuration from %s>' % self.fileName) 
     for s in p.sections(): 
      result.append('[%s]' % s) 
      for o in p.options(s): 
       result.append('%s=%s' % (o, p.get(s, o))) 
     return '\n'.join(result) 

class Section: 
    def __init__ (self, name, parser): 
     self.__name = name 
     self.__parser = parser 

    def __getattr__ (self, name): 
     if self.__dict__.has_key(name):  # any normal attributes are handled normally 
      return __getattr__(self, item) 
     else: 
      return self.__parser.get(self.name, name) 

    def __setattr__(self, item, value): 
     """Maps attributes to values. 
     Only if we are initialised 
     """ 
     if self.__dict__.has_key(item):  # any normal attributes are handled normally 
      dict.__setattr__(self, item, value) 
     else: 
      self.__parser.set('UserOptions',item, value) 

Jetzt frage ich mich, warum in self.__parser.set('UserOptions',item, value) ich den Fehler. Ich lese in den Pythons und ich verstehe nicht, was ich tun soll. Ich vermute, dass ich ein Diktat mit dem Feldnamen speichern muss und schaue erst dort aber wie?

+1

Warum verwenden Sie nicht den integrierten Config-Parser? http://docs.python.org/library/configparser.html –

+0

benutze ich, aber ich vergesse, die Importlinie einzufügen ... – mamcx

Antwort

4

Sie versuchen, die Abschnitte auf Anfrage zu erhalten. Es ist jedoch viel einfacher, über Abschnitte und Optionen zu iterieren und sie als Attribut in __init__ hinzuzufügen. Ich habe mein Beispiel bearbeitet, um auch setattr zu unterstützen. Sie Problem erklärt here Sie die Attribute in __setattr__ zuweisen, während Sie __dict__ statt

from ConfigParser import SafeConfigParser 

class Section: 
    def __init__(self, name, parser): 
     self.__dict__['name'] = name 
     self.__dict__['parser'] = parser 

    def __setattr__(self, attr, value): 
     self.__dict__[attr] = str(value) 
     self.parser.set(self.name, attr, str(value)) 

class Configuration(object): 
    def __init__(self, fileName): 
     self.__parser = SafeConfigParser() 
     self.__parser.read(fileName) 
     self.fileName = fileName 
     for section in self.__parser.sections(): 
      setattr(self, section, Section(section, self.__parser)) 
      for option in self.__parser.options(section): 
       setattr(getattr(self, section), option, 
         self.__parser.get(section, option)) 

    def __getattr__(self, attr): 
     self.__parser.add_section(attr) 
     setattr(self, attr, Section(attr, self.__parser)) 
     return getattr(self, attr) 

    def save(self): 
     f = open(self.fileName, 'w') 
     self.__parser.write(f) 
     f.close() 

c = Configuration('config.ini') 

print dir(c) -> will print all sections 
print dir(c.UserOptions) -> will print all user options 
print c.UserOptions.sampledate 

c.new.value = 10 
c.save() 
+0

Wirklich ganz nett. –

+0

Das OP verwendete auch ConfigParser (vergaß nur, den Import einzuschließen). –

4

Ihr Problem ist in Section.__init__ verwenden sollten. Wenn Sie self.__name = name gesetzt ruft Ihre __setattr__ Methode, findet den Schlüssel nicht in __dict__ so geht es zu

self.__parser.set('UserOptions',item, value) 

So, jetzt muss es self.__parser.

Welche wurde noch nicht festgelegt. Also versucht es mit __getattr__. Welches sendet es auf der Suche nach self.__parser. Was noch nicht eingestellt ist. Also versucht es mit __getattr__. So ... Sie erhalten den Punkt :-)

Eine Möglichkeit, dies zu vermeiden, ist durch eine Bedingung in Section.__setattr__ Zugabe ähnlichen

if item.startswith('_') or self.__dict__.has_key(item): 
    ^^^^^^^^^^^^^^^^^^^^^^^ 
    ... 

die __name sicher machen und __parser richtig bei der Initialisierung festgelegt werden.

+0

Auch! Danke für die Eingabe. – mamcx

Verwandte Themen