ConfigParser с элементами Unicode - PullRequest
       46

ConfigParser с элементами Unicode

20 голосов
/ 30 октября 2009

Мои проблемы с ConfigParser продолжаются. Кажется, он не очень хорошо поддерживает Unicode. Файл конфигурации действительно сохраняется как UTF-8, но когда ConfigParser читает его, он, похоже, кодируется во что-то другое. Я предположил, что это латиница-1, и я думаю, что переопределение optionxform может помочь:

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

Конечно, когда я читаю конфиг, я получаю:

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

Я пробовал несколько различных вариаций декодирования «s», но дело, кажется спорным, так как это действительно должно быть юникода объект с самого начала. В конце концов, файл конфигурации UTF-8? Я подтвердил, что что-то не так в том, как ConfigParser читает файл, заглушая его этим классом DummyConfig. Если я этим воспользуюсь, то все в порядке, юникод, отлично и модно.

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

Любые идеи, которые могут быть причиной этого, или предложения других конфигурационных модулей, которые лучше поддерживают Unicode, приветствуются. Я не хочу использовать sys.setdefaultencoding()!

Ответы [ 6 ]

20 голосов
/ 30 октября 2009

Метод ConfigParser.readfp() может принимать файловый объект, вы пытались открыть объект файла с правильной кодировкой с использованием модуля кодеков перед отправкой его в ConfigParser, как показано ниже:

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

Для Python 3.2 или выше, readfp() устарело. Вместо этого используйте read_file().

2 голосов
/ 26 июля 2017

Попробуйте переписать функцию write в RawConfigParser() следующим образом:

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")
1 голос
/ 22 марта 2018

В Python 3.2 encoding параметр был введен в read(), поэтому теперь его можно использовать как:

cfg.read("myconfig", encoding='utf-8')
1 голос
/ 02 февраля 2016

Кажется, что это проблема с версией ConfigParser для python 2x, и версия для 3x свободна от этой проблемы. В этом выпуске Python Bug Tracker статус закрыт + WONTFIX.

Я исправил это, отредактировав файл ConfigParser.py. В методе записи (о строке 412) измените:

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

от

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

Я не знаю, является ли это реальным решением, но протестировано в Windows 7 и Ubuntu 15.04, работает как чудо, и я могу использовать один и тот же файл .ini в обеих системах и работать с ним.

1 голос
/ 16 декабря 2011

Модуль config не работает при чтении и записи строк в кодировке Unicode в качестве значений. Я попытался это исправить, но странным образом попал в ловушку парсера.

0 голосов
/ 11 октября 2018

То, что я сделал, это просто:

file_name = file_name.decode("utf-8")
cfg.read(file_name)
...