Schodemeiss
Schodemeiss

Reputation: 1174

Recursive Error when introducing setattr in python

I am trying to write a simple object in python that will load up settings using ConfigParser, get all the items as a dictionary, then set those as attributes for the object.

This seems to work if I don't include a __setattr__ method. I can call "settings.top_travel" and get the answer back. However, as soon as I try and put a __setattr__, I seem to get an error.

It looks fairly recursive, so I assume Get is calling Set, etc. In the set attribute part, I wish to make it write back to the configuration file. So, whenever one of the settings attributes changes, it gets stored back in the file where it came from.

Below you will find the code and the error.

import ConfigParser

class settingsFile(object):

    def __init__(self):

        """
        Reloads the configuration file and returns a dictionary with the 
        settings :
        [config]
        top_travel = 250
        """
        # Create a configuration object and read in the file
        configuration = ConfigParser.ConfigParser()
        configuration.read('config/config.cfg')

        # Return all the "config" section as a list and convert to a dictionary
        self.configuration = dict(configuration.items("config"))

    def refresh(self):

        self.__init__()

    def __getattr__(self, attr):
        return self.configuration[attr]

    def __setattr__(self, attr, value):
        print attr, " is now ", value
        # Do some clever storing with ConfigParser

if __name__ == "__main__":

    settings = settingsFile()
    print settings.top_travel
    settings.top_travel = 600
    print settings.top_travel

Error:

Traceback (most recent call last):
  File "/home/stuff/Documents/Software/Python/dBControllers v2/dBControllers.py", line 52, in <module>
    settings = settingsFile()
  File "/home/stuff/Documents/Software/Python/dBControllers v2/dBControllers.py", line 37, in __init__
    self.configuration = dict(configuration.items("config"))
  File "/home/stuff/Documents/Software/Python/dBControllers v2/dBControllers.py", line 47, in __setattr__
    print self.configuration[attr], " is now ", value
  File "/home/stuff/Documents/Software/Python/dBControllers v2/dBControllers.py", line 44, in __getattr__
    return self.configuration[attr]
  File "/home/stuff/Documents/Software/Python/dBControllers v2/dBControllers.py", line 44, in __getattr__
    return self.configuration[attr]
......
RuntimeError: maximum recursion depth exceeded

Upvotes: 3

Views: 2854

Answers (3)

Daniel Hepper
Daniel Hepper

Reputation: 29967

The problem is that setting self.configuration invokes self.__setattr__

You can circumvent that by changing the assignment to a call to __setattr__ of the super class:

class settingsFile(object):

    def __init__(self):
        ...
        # Return all the "config" section as a list and convert to a dictionary
        object.__setattr__(self, 'configuration', dict(configuration.items("config")))

Upvotes: 5

Rosh Oxymoron
Rosh Oxymoron

Reputation: 21055

Make __setattr__ exclusive to attributes not starting with '_', and store the configuration in self._configuration, then add a requirement that configuration files don't accept options whose names start with an underscore.

def __setattr__(self, attribute, value):
     if attribute.startswith('_'):
          super(settingsFile, self).__setattr__(attribute, value)
          return
     # Clever stuff happens here

Upvotes: 5

Rafe Kettler
Rafe Kettler

Reputation: 76955

Whatever clever stuff you're doing with ConfigParser is recursing infinitely. I can't be certain because I don't see the code, but if you're using recursion, make sure you cover all of your base cases.

Upvotes: -3

Related Questions