在Python中引入setattr时出现递归错误

3 投票
3 回答
2834 浏览
提问于 2025-04-16 07:38

我正在尝试用Python写一个简单的对象,这个对象会使用ConfigParser来加载设置,然后把所有的设置项以字典的形式获取出来,再把这些设置项作为对象的属性。

如果我包含__setattr__方法,这个方法就能正常工作。我可以调用“settings.top_travel”并得到正确的结果。但是,一旦我尝试添加__setattr__,就会出现错误。

看起来这个过程有点像递归,所以我猜Get在调用Set,等等。在设置属性的部分,我希望能把更改写回配置文件。因此,每当某个设置属性发生变化时,它就会被存回最初的文件中。

下面是代码和错误信息。

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

错误:

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

3 个回答

-3

你在使用ConfigParser的时候,可能遇到了无限循环的问题。虽然我看不到你的代码,不能完全确定,但如果你在用递归的方式处理问题,一定要确保你考虑到了所有的基本情况。

5

__setattr__ 只对那些名字不以 '_' 开头的属性有效,并把这些设置存储在 self._configuration 里。同时,要求配置文件中的选项名不能以下划线开头。

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

问题在于,设置自定义的配置时,会触发 self.__setattr__ 这个方法。

你可以通过把赋值改成调用父类的 __setattr__ 方法来解决这个问题:

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

撰写回答