2012-03-26 10 views
8

trato de analizar el archivo como:de análisis configure con mismo nombre de sección en Python

[account] 
User = first 

[account] 
User = second 

utilizo ConfigParser en Python, pero cuando leí archivo:

Config = configparser.ConfigParser() 
Config.read(file) 
print (Config.sections()) 

tengo error:

While reading from ... : section 'account' already exists 

¿Cómo puedo analizar este archivo? ¿Hay alguna otra biblioteca? (prefiera para python3)

+0

¿Tiene control sobre el formato de archivo de configuración? Si es así, cámbialo a algo que le guste a 'configparser'. –

+0

No puedo cambiar el formato de archivo. – ExyTab

+0

Sugiero que escriba su propio analizador para ello. – aquavitae

Respuesta

10

Si lo que quiere es simplemente fusionar secciones con nombres idénticos (la última gana), simplemente pase la opción strict=False al constructor (agregado en Python 3.2). Se obtiene efectivamente dict.update() comportamiento como las secciones duplicadas se fusionaron en.

Config = configparser.ConfigParser(strict=False) 

Sin embargo, es claro a partir de datos de la muestra de la OP que las secciones con nombres idénticos deben mantenerse separados, para evitar la pérdida de datos. ConfigParser almacena las secciones que lee en un diccionario, por lo que no puede manejar varias secciones con el mismo nombre. Afortunadamente, el constructor acepta un argumento dict_type que le permite especificar un objeto similar a un diccionario. Puede usar eso para soportar secciones con nombres idénticos. Aquí hay una solución simple que altera los nombres de las secciones al agregar un número único cada vez que se ha visto un nombre de sección.

from collections import OrderedDict 

class multidict(OrderedDict): 
    _unique = 0 # class variable 

    def __setitem__(self, key, val): 
     if isinstance(val, dict): 
      self._unique += 1 
      key += str(self._unique) 
     OrderedDict.__setitem__(self, key, val) 

Config = configparser.ConfigParser(defaults=None, dict_type=multidict, strict=False) 

Con un poco de trabajo, debería ser capaz de construir una solución más limpia.

1

Desafortunadamente, el formato del archivo ini proporcionado no es el correcto según las normas. El nombre de una sección debe ser único en el documento.

Si se puede cambiar el formato de archivo (ya leído que no se puede, pero para redondear ...), a continuación, una solución de este tipo sería apropiado:

[accounts] 
keys= account1, account2 

[account1] 
User = first 

[account2] 
User = second 

Si realmente no puede alternar el formato del archivo, entonces me temo que su única opción es analizar manualmente el archivo de configuración.

0

" Si te estás desviando de un estándar de RFC y estás creando tu propio formato de configuración, vas a tener que escribir tu propio analizador". Este http://www.tek-tips.com/viewthread.cfm?qid=1110829 funcionó para mí. Hice un par de pequeños cambios. ** formateo no sale correctamente cuando se publiquen

def configToDict(file): 
# open the file 
file = open('settings.cfg') 

# create an empty dict 
sections = {} 

for line in file.readlines(): 
    # get rid of the newline 
    line = line[:-1] 
    try: 
     # this will break if you have whitespace on the "blank" lines 
     if line: 
      # skip comment lines 
      if line[0] == '#': next 
      # this assumes everything starts on the first column 
      if line[0] == '[': 
       # strip the brackets 
       section = line[1:-1] 
       # create a new section if it doesn't already exist 
       if not sections.has_key(section): 
        sections[section] = {} 
      else: 
       # split on first the equal sign 
       (key, val) = line.split('=', 1) 
       # create the attribute as a list if it doesn't 
       # exist under the current section, this will 
       # break if there's no section set yet 
       if not sections[section].has_key(key): 
        sections[section][key] = [] 
       # append the new value to the list 
       sections[section][key].append(val) 
    except Exception as e: 
     print str(e) + "line:" +line 
return sections 
2

En la última pitón no es una opción que puede hacer lo que quiera: ConfigParser(strict=True)

Cf: https://docs.python.org/3/library/configparser.html#configparser.ConfigParser

+0

No, no lo hace, al menos no hace lo que el OP estaba buscando y aceptó. 'strict = True' es el valor predeterminado. Establecerlo en 'False' permite múltiples secciones con el mismo nombre, pero simplemente combina sus opciones. – alexis

Cuestiones relacionadas