2009-10-30 3 views
17

mes problèmes avec ConfigParser continuent. Il semble qu'il ne supporte pas très bien l'Unicode. Le fichier de configuration est en effet sauvegardé en UTF-8, mais lorsque ConfigParser le lit, il semble être encodé dans quelque chose d'autre. Je suppose qu'il était latin-1 et je thougt remplaçant optionxform pourrait aider:ConfigParser avec les éléments 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") 

Bien sûr, quand je lis la config je reçois:

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

J'ai essayé deux différentes variantes de décodage 's' mais le point semble sans objet, car il devrait vraiment être un objet unicode depuis le début. Après tout, le fichier de configuration est UTF-8? J'ai confirmé que quelque chose ne va pas dans la façon dont ConfigParser lit le fichier en l'écrasant avec cette classe DummyConfig. Si j'utilise ça alors tout est bien unicode, bien et 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 

Toutes les idées ce qui pourrait être la cause ou des suggestions d'autres modules de configuration qui prend en charge mieux Unicode sont les bienvenus. Je ne veux pas utiliser sys.setdefaultencoding()!

+0

Le bonhomme de neige ne fait pas partie du 'latin-1' – u0b34a0f6ae

+0

Ne jamais faire' l'exception Exception'; attraper l'exception réelle, vous savez comment gérer. –

Répondre

19

La méthode ConfigParser.readfp() peut prendre un objet fichier, avez-vous essayé d'ouvrir l'objet fichier avec l'encodage correct en utilisant le module codecs avant de l'envoyer à ConfigParser comme ci-dessous:

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

Pour Python 3.2 ou au-dessus, readfp() est obsolète. Utilisez read_file() à la place.

+1

J'ai eu le même problème et résolu de la même façon à lire à partir du fichier de configuration. Mais j'ai aussi besoin de réécrire une version modifiée de celle-ci et qui échoue même si j'utilise un codecs.open: 'avec codecs.open (nom de fichier, encoding = ENCODING, mode = 'wb') comme conffile: config.write (conffile) ' –

+0

Salut Ghislain, j'ai le même problème avec configparser pour réécrire une chaîne unicode. Il est résolu en mettant à jour le à la dernière version par pip. – Erxin

1

Le module de configuration est interrompu lors de la lecture et de l'écriture de chaînes Unicode en tant que valeurs. J'ai essayé de résoudre le problème, mais j'ai été rattrapé de façon étrange par l'analyseur.

1

Semble être un problème avec la version de ConfigParser pour python 2x, et la version pour 3x est libre de ce problème. Dans this issue of the Python Bug Tracker, l'état est Fermé + WONTFIX. J'ai corrigé le fichier ConfigParser.py. Dans la méthode d'écriture (de la ligne 412), changer:

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

par

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

Je ne sais pas si c'est une vraie solution, mais testé dans Windows 7 et Ubuntu 15.04, fonctionne comme un charme, et je peux partager et travailler avec le même fichier .ini dans les deux systèmes.

2

Essayez de remplacer la fonction write dans RawConfigParser() comme ceci:

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

Vous pouvez également appliquer un patch-sing à RawConfigParser: 'RawConfigParser.write = write' –