2009-10-30 5 views
17

meine Probleme mit ConfigParser fortsetzen. Es scheint Unicode sehr gut zu unterstützen. Die Konfigurationsdatei wird zwar als UTF-8 gespeichert, aber wenn ConfigParser sie liest, scheint sie in etwas anderes kodiert zu sein. Ich nahm an, es war Latein-1 und ich thougt optionxform zwingende helfen könnte:ConfigParser mit Unicode-Elementen

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

Natürlich, wenn ich die Config las ich bekommen:

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

ich ein paar verschiedene Varianten ausprobiert habe Decodierung 's' aber der Punkt scheint strittig, da es eigentlich ein Unicode-Objekt von Anfang an sein sollte. Immerhin ist die Konfigurationsdatei UTF-8? Ich habe bestätigt, dass etwas nicht stimmt, wenn ConfigParser die Datei liest, indem er sie mit dieser DummyConfig-Klasse ausgibt. Wenn ich das benutze dann ist alles schön Unicode, fein und 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 

Irgendwelche Ideen, was diese oder Vorschläge von anderen Konfigurationsmodule, die Unicode besser unterstützt werden verursachen könnte sehr willkommen. Ich möchte nicht sys.setdefaultencoding() verwenden!

+0

Der Schneemann ist nicht Teil von 'Latin-1 ' – u0b34a0f6ae

+0

Nie tun' außer Exception'; Fange die tatsächliche Ausnahme, mit der du umgehen kannst. –

Antwort

19

Die ConfigParser.readfp() Methode kann ein Dateiobjekt nehmen, haben Sie versucht, das Dateiobjekt mit der richtigen Codierung öffnen, bevor Sie die Codecs Modul es ConfigParser Senden wie unten:

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

für Python 3.2 oder höher, readfp() ist veraltet. Verwenden Sie stattdessen read_file().

+1

Ich hatte das gleiche Problem und löste es auf die gleiche Weise zu lesen aus der Konfigurationsdatei. Aber ich muss auch eine modifizierte Version davon neu schreiben und das scheitert auch, wenn ich einen codecs.open: 'mit codecs.open (filename, encoding = ENCODING, mode = 'wb') als conffile verwende: config.write (conffile) ' –

+0

Hallo Ghislain, ich habe das gleiche Problem mit configparser, um Unicode-String zurückzuschreiben. Es ist gelöst, indem Sie es auf die neueste Version von Pip aktualisieren. – Erxin

1

Das Konfigurationsmodul ist defekt, wenn Unicode-Strings als Werte gelesen und geschrieben werden. Ich habe versucht, es zu beheben, aber ich habe mich auf die seltsame Art verfangen, wie der Parser funktioniert.

1

Scheint, ein Problem mit der ConfigParser-Version für Python 2x zu sein, und Version für 3x ist frei von diesem Problem. In this issue of the Python Bug Tracker ist der Status Closed + WONTFIX.

Ich habe es behoben Bearbeitung der ConfigParser.py Datei. Bei der Schreibmethode (über der Linie 412) ändern:

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

von

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

Ich weiß nicht, ob es sich um eine wirkliche Lösung ist, sondern arbeitet wie in Windows 7 und Ubuntu 15.04, getestet ein Charme, und ich kann mit der gleichen INI-Datei in beiden Systemen teilen und arbeiten.

2

Versuchen Sie, die write Funktion in RawConfigParser() wie diese zu überschreiben:

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

Sie können den RawConfigParser auch mit einem Patch versehen: 'RawConfigParser.write = write' –