Czy zachować wielkość liter w ConfigParser?

90

Próbowałem użyć modułu ConfigParser języka Python, aby zapisać ustawienia. W przypadku mojej aplikacji ważne jest, aby zachować wielkość liter w każdej z sekcji. Dokumentacja wspomina, że ​​przekazanie str () do ConfigParser.optionxform () mogłoby to osiągnąć, ale nie działa to dla mnie. Nazwy są pisane małymi literami. Czy coś mi brakuje?

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

Pseudokod w Pythonie tego, co otrzymuję:

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
źródło

Odpowiedzi:

114

Dokumentacja jest myląca. Co mają na myśli to:

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

To znaczy nadpisuj optionxform, zamiast ją wywoływać; nadpisywanie można wykonać w podklasie lub w instancji. Podczas zastępowania ustaw go na funkcję (zamiast wyniku wywołania funkcji).

Zgłosiłem to jako błąd i od tego czasu został on naprawiony.

Martin przeciwko Löwis
źródło
Dziękuję Ci. To działa i zgadzam się, że doktorzy są mylący.
pojo
39

U mnie pracował nad ustawieniem optionxform natychmiast po utworzeniu obiektu

config = ConfigParser.RawConfigParser()
config.optionxform = str 
ulitosCoder
źródło
2
Działa świetnie! (zwróć uwagę, że w Pythonie 3 jest to nazwa klasy „configparser” (bez wielkich liter)
Noam Manos
1
@NoamManos: Odnosisz się do nazwy modułu (nazwa klasy to nadal ConfigParser ).
Jonas Byström
2
Zauważ, że działa również zConfigParser.ConfigParser()
Jean-Francois T.,
W rzeczy samej. To działa. Warto wspomnieć, że ten parametr nie jest zasadniczo powiązany z RawConfigParser (), ponieważ obsługuje również klasę ConfigParser (). Dzięki stary.
ivanleoncz
7

Dodaj do swojego kodu:

config.optionxform = lambda option: option  # preserve case for letters
FooBar167
źródło
1
Wydaje się, że działa to dla mnie przynajmniej w Pythonie 2.7 i jest znacznie czystsze niż akceptowana odpowiedź. Dzięki, foo!
hrbdg
2
to jest to samo, co najwyżej punktowana odpowiedź - patrz wiersz config.optionxform=str:) tylko zamiast twojego lamdba @Martin v. Löwis używa wbudowanej strfunkcji
xuthus
@xuthus - Rzeczywiście, możesz użyć 11 linii kodu zamiast 1 linii. Jak chcesz.
FooBar167
4

Wiem, że udzielono odpowiedzi na to pytanie, ale pomyślałem, że niektórzy ludzie mogą uznać to rozwiązanie za przydatne. Jest to klasa, która może łatwo zastąpić istniejącą klasę ConfigParser.

Edytowano w celu uwzględnienia sugestii @ OozeMeister:

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

Użycie jest takie samo jak w przypadku zwykłego ConfigParser.

parser = CaseConfigParser()
parser.read(something)

Dzięki temu unikniesz konieczności ustawiania optionxform za każdym razem, gdy tworzysz nowy ConfigParser, co jest trochę żmudne.

icedtrees
źródło
Ponieważ optionxformjest to tylko metoda na platformie RawConfigParser, jeśli masz zamiar posunąć się do tworzenia własnej podklasy, powinieneś zamiast tego po prostu nadpisać metodę w podklasie, zamiast redefiniować ją dla każdej instancji:class CaseConfigParser(ConfigParser): def optionxform(self, optionstr): return optionstr
OozeMeister
@OozeMeister świetny pomysł!
icedtrees
2

Ostrzeżenie:

Jeśli używasz wartości domyślnych z ConfigParser, tj .:

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

a następnie spróbuj rozróżniać wielkość liter w parserze, używając tego:

config.optionxform = str

wszystkie opcje z plików konfiguracyjnych zachowają wielkość liter, ale FOO_BAZzostaną przekonwertowane na małe litery.

Aby wartości domyślne również zachowywały wielkość liter, użyj podklas, jak w odpowiedzi @icedtrees:

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

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

Teraz FOO_BAZzachowa wielkość liter i nie będziesz mieć InterpolationMissingOptionError .

nidalpres
źródło