2009-10-30 15 views
17

I problemi con ConfigParser continuano. Sembra che non supporti molto bene Unicode. Il file di configurazione è infatti salvato come UTF-8, ma quando ConfigParser lo legge sembra essere codificato in qualcos'altro. Ho pensato che era latin-1 e ho thougt sovrascrivendo optionxform potrebbe aiutare:ConfigParser con elementi 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") 

Naturalmente, quando ho letto la configurazione ottengo:

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

Ho provato un paio di diverse varianti di decodifica 's' ma il punto sembra discutibile, dal momento che dovrebbe essere un oggetto unicode dall'inizio. Dopotutto, il file di configurazione è UTF-8? Ho confermato che c'è qualcosa di sbagliato nel modo in cui ConfigParser legge il file estraendolo con questa classe DummyConfig. Se lo uso, allora tutto è univoco, bello e dandy.

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

Tutte le idee che potrebbero essere la causa di questo o suggerimenti di altri moduli di configurazione che supporta Unicode migliori sono i benvenuti. Non voglio usare sys.setdefaultencoding()!

+0

Il pupazzo di neve non fa parte del 'latino-1' – u0b34a0f6ae

+0

Mai e poi mai fare' tranne Exception'; prendi l'effettiva eccezione che sai come gestire. –

risposta

19

Il metodo ConfigParser.readfp() può prendere un oggetto file, hai provato ad aprire l'oggetto file con la codifica corretta utilizzando il modulo codecs prima di inviarlo al ConfigParser come di seguito:

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

Per Python 3.2 o superiore, readfp() è deprecato. Utilizzare invece read_file().

+1

Ho avuto lo stesso problema E lo ho risolto allo stesso modo di leggere dal file di configurazione. Ma ho anche bisogno di riscrivere una versione modificata di esso e che fallisce anche se uso un codecs.open: 'con codecs.open (filename, encoding = ENCODING, mode = 'wb') come conffile: config.write (conffile) ' –

+0

Ciao Ghislain, Ho lo stesso problema con configparser per scrivere una stringa unicode. È risolto aggiornando il file con l'ultima versione di pip. – Erxin

1

Il modulo di configurazione è danneggiato durante la lettura e la scrittura di stringhe unicode come valori. Ho provato a risolverlo, ma sono rimasto intrappolato nello strano modo in cui funziona il parser.

1

Sembra essere un problema con la versione di ConfigParser per python 2x e la versione per 3x è esente da questo problema. In this issue of the Python Bug Tracker, lo stato è Chiuso + WONTFIX.

L'ho risolto modificando il file ConfigParser.py. Nel metodo write (sulla linea 412), cambiare:

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

da

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

Non so se si tratta di una vera e propria soluzione, ma testato in Windows 7 e Ubuntu 15.04, funziona come un fascino, e posso condividere e lavorare con lo stesso file .ini in entrambi i sistemi.

2

prova a sovrascrivere la funzione write in RawConfigParser() come questo:

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

È anche possibile eseguire il patch delle scimmie su RawConfigParser: 'RawConfigParser.write = write' –

Problemi correlati