Рекурсивная ошибка при введении setattr в python

Я пытаюсь написать простой объект на python, который будет загружать настройки с помощью ConfigParser, получать все элементы в виде словаря, а затем устанавливать их как атрибуты для объекта.

Кажется, это работает, если я не включаю метод __setattr__. Я могу позвонить в «settings.top_travel» и получить ответ. Однако, как только я пытаюсь поставить __setattr__, я получаю сообщение об ошибке.

Это выглядит довольно рекурсивно, поэтому я предполагаю, что Get вызывает Set и т. д. В части атрибута 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

person Schodemeiss    schedule 26.11.2010    source источник
comment
Возможно, вы просто хотите voidspace.org.uk/python/configobj.html   -  person Jochen Ritzel    schedule 26.11.2010
comment
Какая конкретно ошибка? Например. ValueError и т. д.   -  person Rafe Kettler    schedule 26.11.2010
comment
@Rafe: я обновил ошибку в нижней части исходного сообщения, добавив более полное сообщение об ошибке.   -  person Schodemeiss    schedule 26.11.2010


Ответы (3)


Проблема в том, что настройка self.configuration вызывает 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")))
person Daniel Hepper    schedule 26.11.2010
comment
object.__setattr__() принимает 3 параметра. Вы забыли передать «я» в качестве первого. - person edon; 26.11.2010

Сделайте __setattr__ исключительным для атрибутов, не начинающихся с '_', и сохраните конфигурацию в self._configuration, затем добавьте требование, чтобы файлы конфигурации не принимали параметры, имена которых начинаются с подчеркивания.

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

Какие бы умные вещи вы ни делали с ConfigParser, они бесконечно повторяются. Я не могу быть уверен, потому что не вижу кода, но если вы используете рекурсию, убедитесь, что вы охватываете все свои базовые случаи.

person Rafe Kettler    schedule 26.11.2010