Domanda

i miei problemi con ConfigParser continuano. Sembra che non supporti molto bene Unicode. Il file di configurazione viene effettivamente salvato come UTF-8, ma quando ConfigParser lo legge sembra essere codificato in qualcos'altro. Ho pensato che fosse latino-1 e ho pensato che scavalcare optionxform potesse aiutare:

-- 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 leggo 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. Dopo tutto, il file di configurazione è UTF-8? Ho confermato che qualcosa non va nel modo in cui ConfigParser legge il file cancellandolo con questa classe DummyConfig. Se lo uso, allora tutto è bello Unicode, bene 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  

Qualunque idea su cosa potrebbe causare questo o suggerimenti di altri moduli di configurazione che supportano meglio Unicode sono i benvenuti. Non voglio usare sys.setdefaultencoding () !

È stato utile?

Soluzione

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

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

Per Python 3.2 o versioni successive, readfp () è obsoleto. Usa read_file () invece.

Altri suggerimenti

Prova a sovrascrivere la funzione write in RawConfigParser () in questo modo:

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

Il modulo di configurazione viene interrotto durante la lettura e la scrittura di stringhe unicode come valori. Ho provato a risolverlo, ma sono stato catturato nello strano modo in cui funziona il parser.

Sembra essere un problema con la versione di ConfigParser per Python 2x e la versione per 3x è priva di questo problema. In questo numero di Python Bug Tracker , lo stato è Chiuso + WONTFIX.

L'ho corretto modificando il file ConfigParser.py. Nel metodo di scrittura (sulla riga 412), modifica:

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 sia una vera soluzione, ma testato in Windows 7 e Ubuntu 15.04, funziona come un incantesimo e posso condividere e lavorare con lo stesso file .ini in entrambi i sistemi.

In python 3.2 encoding il parametro è stato introdotto in read () , quindi ora può essere usato come:

cfg.read("myconfig", encoding='utf-8')

quello che ho fatto è solo:

file_name = file_name.decode("utf-8")
cfg.read(file_name)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top