2008-11-13 13 views
8

Leí la parte de the docs y vi que ConfigParser devuelve una lista de pares clave/valor para las opciones dentro de una sección. Pensé que las claves no necesitaban ser únicas dentro de una sección, de lo contrario, el analizador solo devolvería una asignación. Diseñé mi esquema de archivo de configuración en torno a esta suposición, entonces se dio cuenta con tristeza que este no es el caso:Teclas exclusivas ConfigParser de Python por sección

>>> from ConfigParser import ConfigParser 
>>> from StringIO import StringIO 
>>> fh = StringIO(""" 
... [Some Section] 
... spam: eggs 
... spam: ham 
... """) 
>>> parser = ConfigParser() 
>>> parser.readfp(fh) 
>>> print parser.items('Some Section') 
[('spam', 'ham')] 

Luego volví y encontró la parte de la documentación que debería leído:

Las secciones se almacenan normalmente en un diccionario incorporado . Se puede pasar un tipo de diccionario alternativo al constructor ConfigParser . Por ejemplo, si se pasa un tipo de diccionario que ordena sus claves, las secciones serán ordenadas en write-back, al igual que las claves dentro de cada sección.

Para mantener mi esquema de archivo de configuración existente (que realmente me gusta ahora;) estoy pensando en pasar un objeto similar a un mapeo como se mencionó anteriormente que acumula valores en lugar de destruirlos. ¿Hay alguna manera más simple de evitar el colapso de clave/valor que me falta? En lugar de hacer un adaptador loco (que podría romperse si cambia la implementación de ConfigParser) ¿debería escribir una variante del ConfigParser?

Siento que este puede ser uno de esos momentos 'duh' en los que solo veo las soluciones difíciles.

[Editar:] Aquí hay un ejemplo más preciso de la forma en que me gustaría utilizar la misma clave varias veces:

[Ignored Paths] 
ignore-extension: .swp 
ignore-filename: tags 
ignore-directory: bin 

No me gusta la sintaxis de la lista separada por comas, porque es difícil en el ojos cuando lo escalas a muchos valores; por ejemplo, una lista delimitada por comas de cincuenta extensiones no sería particularmente legible.

+1

Creo que usar listas sería más legible que 50 líneas de 'ignorar-extensión: ...' –

+1

¿De verdad? No estoy de acuerdo ... con cada uno en una línea separada, puedes escanear la lista: nunca he encontrado listas delimitadas por comas de extensiones de tres letras para ser bonita. También anticipo que las personas quieran comentar fácilmente cualquier opción dada, a lo que se dirigen las líneas separadas. – cdleary

Respuesta

11

ConfigParser no está diseñado para manejar tales condiciones. Además, tu archivo de configuración no tiene sentido para mí.

ConfigParser le proporciona una estructura similar a un dictado para cada sección, por lo que cuando llame a parser.items (sección), estoy esperando un resultado similar a dict.items(), que es solo una lista de tuplas clave/valor . Yo nunca esperaría a ver algo como:

[('spam', 'eggs'), ('spam', 'ham')] 

no hablar, ¿cómo esperar lo siguiente ?: a comportarse

parser.get('Some Section', 'spam') 

Cuál es la forma pretendida para recuperar valores.

Si desea almacenar varios valores para la misma clave, sugeriría algo como esto en el fichero de configuración:

[Some Section] 
spam: eggs, ham 

Y esto en su código:

spam_values = [v.strip() for v in parser.get('Some Section', 'spam').split(',')] 

Por supuesto, esto solo funcionará para valores que no contengan comas o que no manejen comillas.Para eso, debe emplear una técnica más avanzada (consulte this y this).

EDITAR: Si no le molesta la dependencia adicional, puede consultar ConfigObj, que admite listas nativamente como un tipo de valor.

+0

Esperaría que 'parser.get' devuelva el primer o el último valor asociado con la clave. Esperaba que la configuración se almacenara * internamente * como elementos. No me gusta la sintaxis de la lista porque es más difícil de mirar pero tendré que cambiar. – cdleary

+0

Estoy especulando, pero creo que una dicción sería una clase base más eficiente para una sección. Si este es el caso, explicaría el comportamiento. De cualquier manera, te vas a dar un gran dolor de cabeza tratando de hacer que haga lo que quieras. –

+0

Bastante justo. Tengo suficientes dolores de cabeza como están. :) – cdleary

0

Esta deficiencia de ConfigParser es la razón por la Pyglet utiliza para reemplazar patched version of epydoc ConfigParser ini con esta simple format:

name: pyglet 
url: http://www.pyglet.org/ 

output: html 
target: doc/api/ 
...  
module: pyglet 

exclude: pyglet.gl.gl 
exclude: pyglet.gl.agl 
exclude: pyglet.gl.lib_agl 
exclude: pyglet.gl.wgl 
... 

Si no es necesario secciones - este enfoque puede ser útil.

Cuestiones relacionadas