Сохранить регистр в ConfigParser?

90

Я попытался использовать модуль Python ConfigParser для сохранения настроек. Для моего приложения важно, чтобы я сохранял регистр каждого имени в моих разделах. В документах упоминается, что передача str () в ConfigParser.optionxform () сделает это, но для меня это не работает. Имена все в нижнем регистре. Я что-то упускаю?

<~/.myrc contents>
[rules]
Monkey = foo
Ferret = baz

Псевдокод Python того, что я получаю:

import ConfigParser,os

def get_config():
   config = ConfigParser.ConfigParser()
   config.optionxform(str())
    try:
        config.read(os.path.expanduser('~/.myrc'))
        return config
    except Exception, e:
        log.error(e)

c = get_config()  
print c.options('rules')
[('monkey', 'foo'), ('ferret', 'baz')]
Pojo
источник

Ответы:

114

Документация сбивает с толку. Они имеют в виду следующее:

import ConfigParser, os
def get_config():
    config = ConfigParser.ConfigParser()
    config.optionxform=str
    try:
        config.read(os.path.expanduser('~/.myrc'))
        return config
    except Exception, e:
        log.error(e)

c = get_config()  
print c.options('rules')

Т.е. переопределить optionxform вместо ее вызова; переопределение может быть выполнено в подклассе или в экземпляре. При переопределении установите для него функцию (а не результат вызова функции).

Я сообщил об этом как об ошибке , и с тех пор она исправлена.

Мартин против Лёвиса
источник
Спасибо. Это работает, и я согласен, что документы сбивают с толку.
pojo
39

Для меня работал, чтобы установить optionxform сразу после создания объекта

config = ConfigParser.RawConfigParser()
config.optionxform = str 
ulitosCoder
источник
2
Работает отлично! (обратите внимание, что в python 3 это имя класса configparser (без прописных букв)
Ноам Манос,
1
@NoamManos: вы имеете в виду имя модуля (имя класса по-прежнему ConfigParser ).
Йонас Быстрём
2
Обратите внимание, что это тоже работает сConfigParser.ConfigParser()
Jean-Francois T.
На самом деле. Оно работает. Стоит отметить, что этот параметр по существу не связан с RawConfigParser (), поскольку он также поддерживается классом ConfigParser (). Спасибо чувак.
ivanleoncz
7

Добавьте в свой код:

config.optionxform = lambda option: option  # preserve case for letters
FooBar167
источник
1
Кажется, это работает для меня, по крайней мере, в python 2.7 и намного чище, чем принятый ответ. Спасибо, фу!
hrbdg 02
2
это то же самое, что и самый набранный ответ - см. строчку config.optionxform=str:) только вместо вашей lamdba @Martin v. Löwis использует встроенную strфункцию
xuthus
@xuthus - Действительно, вы можете использовать 11 строк кода вместо 1 строки. Как ты любишь.
FooBar167,
4

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

Отредактировано с учетом предложения @OozeMeister:

class CaseConfigParser(ConfigParser):
    def optionxform(self, optionstr):
        return optionstr

Использование такое же, как и в обычном ConfigParser.

parser = CaseConfigParser()
parser.read(something)

Это сделано для того, чтобы вам не приходилось устанавливать optionxform каждый раз, когда вы создаете новый ConfigParser, что довольно утомительно.

ледовые деревья
источник
Поскольку optionxformэто всего лишь метод RawConfigParser, если вы собираетесь создать собственный подкласс, вам следует вместо этого просто переопределить метод подкласса, а не переопределять его для каждого экземпляра:class CaseConfigParser(ConfigParser): def optionxform(self, optionstr): return optionstr
OozeMeister
@OozeMeister отличная идея!
icedtrees
2

Предостережение:

Если вы используете настройки по умолчанию с ConfigParser, то есть:

config = ConfigParser.SafeConfigParser({'FOO_BAZ': 'bar'})

а затем попробуйте сделать синтаксический анализатор чувствительным к регистру, используя это:

config.optionxform = str

все ваши параметры из конфигурационных файлов сохранят свой регистр, но FOO_BAZбудут преобразованы в нижний регистр.

Чтобы значения по умолчанию также оставались неизменными, используйте подклассы, как в ответе @icedtrees:

class CaseConfigParser(ConfigParser.SafeConfigParser):
    def optionxform(self, optionstr):
        return optionstr

config = CaseConfigParser({'FOO_BAZ': 'bar'})

Теперь FOO_BAZоставим это дело, и у вас не будет InterpolationMissingOptionError .

нидальпрес
источник