Préserver la casse dans ConfigParser?

90

J'ai essayé d'utiliser le module ConfigParser de Python pour enregistrer les paramètres. Pour mon application, il est important que je préserve la casse de chaque nom dans mes sections. La documentation mentionne que passer str () à ConfigParser.optionxform () accomplirait cela, mais cela ne fonctionne pas pour moi. Les noms sont tous en minuscules. Est-ce que je manque quelque chose?

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

Pseudocode Python de ce que j'obtiens:

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
la source

Réponses:

114

La documentation est déroutante. Ce qu'ils veulent dire, c'est ceci:

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

Ie surcharger optionxform, au lieu de l'appeler; le remplacement peut être effectué dans une sous-classe ou dans l'instance. Lors de la substitution, définissez-le sur une fonction (plutôt que sur le résultat de l'appel d'une fonction).

J'ai maintenant signalé cela comme un bogue , et il a depuis été corrigé.

Martin c.Löwis
la source
Merci. Cela fonctionne, et je reconnais que les documents prêtent à confusion.
pojo
39

Pour moi, j'ai travaillé à définir optionxform immédiatement après la création de l'objet

config = ConfigParser.RawConfigParser()
config.optionxform = str 
ulitosCoder
la source
2
Fonctionne très bien! (notez que dans python 3, il s'agit du nom de classe "configparser" (pas de majuscules)
Noam Manos
1
@NoamManos: Vous faites référence au nom du module (le nom de la classe est toujours ConfigParser ).
Jonas Byström
2
Notez que ça marche aussi avecConfigParser.ConfigParser()
Jean-Francois
En effet. Ça marche. Il est bon de mentionner que ce paramètre n'est pas associé essentiellement à RawConfigParser (), car il est également pris en charge avec la classe ConfigParser (). Merci mec.
ivanleoncz
7

Ajoutez à votre code:

config.optionxform = lambda option: option  # preserve case for letters
FooBar167
la source
1
Cela semble fonctionner pour moi au moins en python 2.7 et est beaucoup plus propre que la réponse acceptée. Merci foo!
hrbdg
2
c'est la même chose que la réponse config.optionxform=strla mieux notée - voir la ligne :) juste au lieu de votre lamdba @Martin v. Löwis utilise une strfonction intégrée
xuthus
@xuthus - En effet, vous pouvez utiliser 11 lignes de code au lieu d'1 ligne. Comme vous voulez.
FooBar167 le
4

Je sais que cette question a une réponse, mais j'ai pensé que certaines personnes pourraient trouver cette solution utile. C'est une classe qui peut facilement remplacer la classe ConfigParser existante.

Modifié pour intégrer la suggestion de @ OozeMeister:

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

L'utilisation est la même que celle de ConfigParser normal.

parser = CaseConfigParser()
parser.read(something)

C'est ainsi que vous évitez d'avoir à définir optionxform à chaque fois que vous en faites un nouveau ConfigParser, ce qui est assez fastidieux.

arbres de glace
la source
Puisqu'il optionxforms'agit simplement d'une méthode sur le RawConfigParser, si vous allez jusqu'à créer votre propre sous-classe, vous devriez plutôt remplacer la méthode sur la sous-classe plutôt que de la redéfinir par instanciation:class CaseConfigParser(ConfigParser): def optionxform(self, optionstr): return optionstr
OozeMeister
@OozeMeister super idée!
arbres de glace
2

Caveat:

Si vous utilisez les valeurs par défaut avec ConfigParser, c'est-à-dire:

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

puis essayez de rendre l'analyseur sensible à la casse en utilisant ceci:

config.optionxform = str

toutes vos options du ou des fichiers de configuration conserveront leur casse, mais FOO_BAZseront converties en minuscules.

Pour que les valeurs par défaut conservent également leur casse, utilisez la sous-classification comme dans @icedtrees answer:

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

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

Maintenant FOO_BAZ, gardez sa casse et vous n'aurez pas InterpolationMissingOptionError .

nidalpres
la source