ConfigParser с элементами Unicode
мои проблемы с 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()
!
Ответы
Ответ 1
Метод ConfigParser.readfp()
может принимать файл-объект, попробовал ли вы открыть объект файла с правильным кодированием с использованием модуля кодеков перед его отправкой в ConfigParser, как показано ниже:
cfg.readfp(codecs.open("myconfig", "r", "utf8"))
Для Python 3.2 или выше readfp()
устарел. Вместо этого используйте read_file()
.
Ответ 2
Попробуйте перезаписать функцию 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")
Ответ 3
Конфигурационный модуль поврежден при чтении и записи строк юникода в качестве значений. Я попытался это исправить, но оказался странным, как работает парсер.
Ответ 4
Кажется, проблема с версией ConfigParser для python 2x, и версия для 3x не имеет этой проблемы. В этой проблеме Python Bug Tracker статус Closed + 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 файлом в обеих системах.