Как исключить DEFAULT из Python ConfigParser .items ()? - PullRequest
14 голосов
/ 03 февраля 2010

Я использую ConfigParser для загрузки данных из файла конфигурации следующим образом:

test.conf:

[myfiles]
fileone: %(datadir)s/somefile.foo
filetwo: %(datadir)s/nudderfile.foo

load.py:

import ConfigParser

config = ConfigParser.ConfigParser({'datadir': '/tmp'})
config.read('test.conf')

print config.items('myfiles')
print config.get('myfiles', 'datadir')

Выход:

$ python load.py 
[('datadir', '/tmp'), ('filetwo', '/tmp/nudderfile.foo'), ('fileone', '/tmp/somefile.foo')]
/tmp

Я удивлен, что значения по умолчанию для подстановки переменных ('datadir', '/tmp') отображаются как часть. items() и .get() возвратов, как если бы они были значениями в файле конфигурации. Ожидается ли такое поведение? Любой обходной путь, так что я могу просто перебрать .items(), не добавляя туда значения словаря по умолчанию, но все еще используя волшебную интерполяцию?

Ссылка: http://docs.python.org/library/configparser.html

Спасибо!

Обновление: Было отмечено, что это ожидаемое поведение: значения по умолчанию аналогичны любой другой паре имя / значение в файле конфигурации. Точно так же пары имя / значение в файле конфигурации также доступны для «магической интерполяции», поэтому, если я определю:

foo: bar
zap: %(foo)snowl

Я получу [... ('zap': 'barnowl')]

Это довольно аккуратно, но мне все еще интересно, смогу ли я выполнить то, что я хочу сделать: перебирать пары имя / значение в моих файлах конфигурации с интерполяцией переменных без значений по умолчанию.

Мой конкретный сценарий таков: я хотел инициализировать объект конфигурации чем-то вроде {basedir: '/foo/bar'}, так как абсолютные пути к определенным файлам зависят от установки. Затем мне нужно передать этот объект конфигурации и выполнить различные другие классы для перебора файлов. Я не хочу, чтобы каждый класс, который читает конфигурацию, знал, что она была инициализирована с определенными значениями по умолчанию и что он должен игнорировать их, поскольку они не являются реальными файлами. Это возможно? Любой способ скрыть значения по умолчанию от .item () и .get (), но все еще с интерполяцией? Спасибо!

Ответы [ 4 ]

7 голосов
/ 26 сентября 2012

В общем, я нашел класс configparser.Configparser очень полезным, но также отсутствующим. У других тоже есть .

Однако, это может быть разделено на подклассы и расширено, иногда красиво, иногда не так красиво (= очень зависит от реализации)

Вот решение вашей проблемы, протестированное в Python3:

class ConfigParser(configparser.ConfigParser):
    """Can get options() without defaults
    """
    def options(self, section, no_defaults=False, **kwargs):
        if no_defaults:
            try:
                return list(self._sections[section].keys())
            except KeyError:
                raise NoSectionError(section)
        else:
            return super().options(section, **kwargs)

Это один из плохих примеров, потому что он частично копирует исходный код из options(). Было бы лучше, если бы базовый класс configparser RawConfigParser предоставил бы внутренний получатель параметров _options(self, section), который включал бы приведение исключений, и options(), который бы использовал это. Затем в подклассах мы могли бы повторно использовать _options().

Для Python 2 я считаю, что единственное изменение - это super() вызов super(ConfigParser,self).

Затем вы можете использовать:

print config.options('myfiles', no_defaults=True)

А также использовать этот список для итерации.

2 голосов
/ 07 июня 2016

Разве вы не можете просто отфильтровать значения по умолчанию?

например:.

filtered_items = [x for x in config.items('myfiles') if x[0] not in config.defaults()]

1 голос
/ 14 января 2019

Следующее должно дать вам только пары ключ / значение в разделе myfiles , но не перечислять их в DEFAULT :

list(set(config.items('myfiles'))-set(config.items('DEFAULT')))
1 голос
/ 03 февраля 2010

Попробуйте это:

config = ConfigParser.ConfigParser({'blahblahblah': 'blah'})
config.read('test.conf')

Клавиша blahblahblah также появится в items не потому, что это шаблон в INI-файле, а потому, что вы указали его по умолчанию. Вот как ConfigParser обрабатывает значения по умолчанию: если он не может найти их в файле, он назначает их значения по умолчанию.

Так что мне кажется, что у вас здесь простое смешение понятий.

...