¿Conservar caso en ConfigParser?

90

Intenté usar el módulo ConfigParser de Python para guardar la configuración. Para mi aplicación, es importante que conserve el caso de cada nombre en mis secciones. Los documentos mencionan que pasar str () a ConfigParser.optionxform () lograría esto, pero no funciona para mí. Los nombres están todos en minúsculas. ¿Me estoy perdiendo de algo?

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

Pseudocódigo de Python de lo que obtengo:

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
fuente

Respuestas:

114

La documentación es confusa. Lo que quieren decir es esto:

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

Es decir, anule optionxform, en lugar de llamarlo; la invalidación se puede realizar en una subclase o en la instancia. Al anular, establézcalo en una función (en lugar del resultado de llamar a una función).

He informado de esto como un error y desde entonces se ha solucionado.

Martin contra Löwis
fuente
Gracias. Funciona, y estoy de acuerdo en que los documentos son confusos.
pojo
39

Para mí, funcionó para configurar optionxform inmediatamente después de crear el objeto

config = ConfigParser.RawConfigParser()
config.optionxform = str 
ulitosCoder
fuente
2
¡Funciona genial! (tenga en cuenta que en Python 3 es el nombre de la clase "configparser" (sin mayúsculas)
Noam Manos
1
@NoamManos: Te refieres al nombre del módulo (el nombre de la clase sigue siendo ConfigParser ).
Jonas Byström
2
Tenga en cuenta que también funciona conConfigParser.ConfigParser()
Jean-Francois T.
En efecto. Funciona. Es bueno mencionar que este parámetro no está asociado esencialmente a RawConfigParser (), ya que también es compatible con la clase ConfigParser (). Gracias hombre.
ivanleoncz
7

Agregue a su código:

config.optionxform = lambda option: option  # preserve case for letters
FooBar167
fuente
1
Esto parece funcionar para mí al menos en Python 2.7 y es mucho más limpio que la respuesta aceptada. ¡Gracias foo!
hrbdg
2
esto es lo mismo que la respuesta mejor calificada - vea la línea config.optionxform=str:) solo que en lugar de su lamdba @Martin v. Löwis usa la strfunción incrustada
xuthus
@xuthus: de hecho, puede usar 11 líneas de código en lugar de 1 línea. Como quieras.
FooBar167
4

Sé que esta pregunta está respondida, pero pensé que algunas personas podrían encontrar útil esta solución. Esta es una clase que puede reemplazar fácilmente la clase ConfigParser existente.

Editado para incorporar la sugerencia de @OozeMeister:

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

El uso es el mismo que ConfigParser normal.

parser = CaseConfigParser()
parser.read(something)

Esto es para evitar tener que configurar optionxform cada vez que crea una nueva ConfigParser, lo cual es algo tedioso.

árboles helados
fuente
Dado que optionxformes solo un método en el RawConfigParser, si va a ir tan lejos como para crear su propia subclase, en su lugar debe anular el método en la subclase en lugar de redefinirlo por instanciación:class CaseConfigParser(ConfigParser): def optionxform(self, optionstr): return optionstr
OozeMeister
@OozeMeister ¡gran idea!
icedtrees
2

Consideración:

Si usa valores predeterminados con ConfigParser, es decir:

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

y luego intente hacer que el analizador distinga entre mayúsculas y minúsculas usando esto:

config.optionxform = str

todas sus opciones de los archivos de configuración mantendrán su caso, pero FOO_BAZ se convertirán a minúsculas.

Para que los valores predeterminados también mantengan su caso, use subclases como en la respuesta de @icedtrees:

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

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

Ahora FOO_BAZmantendrá su caso y no tendrá InterpolationMissingOptionError .

nidalpres
fuente