2009-10-30 13 views
17

mis problemas con ConfigParser continúan. Parece que no es compatible con Unicode muy bien. El archivo de configuración está realmente guardado como UTF-8, pero cuando ConfigParser lo lee, parece estar codificado en otra cosa. Supuse que era latino-1 y Me vestuario anulando optionxform podría ayudar:ConfigParser con elementos Unicode

-- configfile.cfg -- 
[rules] 
Häjsan = 3 
☃ = my snowman 

-- myapp.py -- 
# -*- coding: utf-8 -*- 
import ConfigParser 

def _optionxform(s): 
    try: 
     newstr = s.decode('latin-1') 
     newstr = newstr.encode('utf-8') 
     return newstr 
    except Exception, e: 
     print e 

cfg = ConfigParser.ConfigParser() 
cfg.optionxform = _optionxform  
cfg.read("myconfig") 

Por supuesto, cuando leí la configuración me sale:

'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128) 

He intentado un par de diferentes variaciones de descifrando 's' pero el punto parece discutible, ya que realmente debería ser un objeto unicode desde el principio. Después de todo, el archivo de configuración es UTF-8? He confirmado que algo está mal en la forma en que ConfigParser lee el archivo anulándolo con esta clase DummyConfig. Si uso eso, entonces todo es lindo Unicode, fino y elegante.

-- config.py -- 
# -*- coding: utf-8 -*-     
apa = {'rules': [(u'Häjsan', 3), (u'☃', u'my snowman')]} 

class DummyConfig(object): 
    def sections(self): 
     return apa.keys() 
    def items(self, section): 
     return apa[section] 
    def add_section(self, apa): 
     pass 
    def set(self, *args): 
     pass 

¿Alguna idea de lo que podría estar causando esto o sugerencias de otros módulos de configuración que mejor soporta Unicode son más que bienvenidos. No quiero usar sys.setdefaultencoding()!

+0

El muñeco de nieve no es parte de 'latino-1' – u0b34a0f6ae

+0

Nunca jamás hacer' excepto Exception'; capte la excepción real que sabe cómo manejar. –

Respuesta

19

El ConfigParser.readfp() método puede tomar un objeto de archivo, ¿ha intentado abrir el objeto de archivo con la codificación correcta utilizando el módulo de códecs antes de enviarlo a ConfigParser, como a continuación:

cfg.readfp(codecs.open("myconfig", "r", "utf8")) 

Para Python 3.2 o superior, readfp() es obsoleto. Use read_file() en su lugar.

+1

Tuve el mismo problema Y lo resolví de la misma manera que LEER desde el archivo de configuración. Pero también necesito reescribir una versión modificada de la misma y eso falla incluso si uso un codecs.open: 'con codecs.open (filename, encoding = ENCODING, mode = 'wb') como conffile: config.write (conffile) ' –

+0

Hola Ghislain, tengo el mismo problema con el configparser para escribir una cadena Unicode. Se resuelve actualizándolo a la última versión de pip. – Erxin

1

El módulo de configuración se interrumpe al leer y escribir cadenas Unicode como valores. Traté de arreglarlo, pero me atrapé de la extraña manera en que funciona el analizador.

1

Parece ser un problema con la versión ConfigParser para python 2x, y la versión para 3x está libre de este problema. En this issue of the Python Bug Tracker, el estado es Cerrado + WONTFIX.

Lo arreglé editando el archivo ConfigParser.py. En el método de escritura (sobre la línea 412), cambie:

key = " = ".join((key, str(value).replace('\n', '\n\t'))) 

por

key = " = ".join((key, str(value).decode('utf-8').replace('\n', '\n\t'))) 

No sé si es una solución real, pero probado en Windows 7 y Ubuntu 15.04, funciona como un encanto, y puedo compartir y trabajar con el mismo archivo .ini en ambos sistemas.

2

intente sustituir la función write en RawConfigParser() así:

class ConfigWithCoder(RawConfigParser): 
def write(self, fp): 
    """Write an .ini-format representation of the configuration state.""" 
    if self._defaults: 
     fp.write("[%s]\n" % "DEFAULT") 
     for (key, value) in self._defaults.items(): 
      fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t'))) 
     fp.write("\n") 
    for section in self._sections: 
     fp.write("[%s]\n" % section) 
     for (key, value) in self._sections[section].items(): 
      if key == "__name__": 
       continue 
      if (value is not None) or (self._optcre == self.OPTCRE): 
       if type(value) == unicode: 
        value = ''.join(value).encode('utf-8') 
       else: 
        value = str(value) 
       value = value.replace('\n', '\n\t') 
       key = " = ".join((key, value)) 
      fp.write("%s\n" % (key)) 
     fp.write("\n") 
+0

También puede parchear mono el RawConfigParser: 'RawConfigParser.write = write' –

Cuestiones relacionadas