25

我对 ConfigParser 的麻烦还在继续。它似乎不太支持Unicode。配置文件确实保存为 UTF-8,但是当 ConfigParser 读取它时,它似乎被编码成其他东西。我认为它是 latin-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' 变体,但这一点似乎没有实际意义,因为它从一开始就应该是一个 unicode 对象。毕竟,配置文件是 UTF-8 的?我已经确认 ConfigParser 通过使用这个 DummyConfig 类将文件存根来读取文件的方式有问题。如果我使用它,那么一切都是很好的 unicode,很好而且花花公子。

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

4

5 回答 5

22

ConfigParser.readfp()方法可以获取文件对象,您是否尝试使用编解码器模块以正确的编码打开文件对象,然后将其发送到 ConfigParser,如下所示:

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

对于 Python 3.2 或更高版本,readfp()已弃用。改为使用read_file()

于 2009-10-30T09:44:13.633 回答
12

在 python 3.2encoding中引入了参数read(),所以它现在可以用作:

cfg.read("myconfig", encoding='utf-8')
于 2018-03-22T12:39:40.253 回答
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")
于 2017-07-26T09:53:21.227 回答
1

python 2x的ConfigParser版本似乎有问题,3x的版本没有这个问题。在本期 Python Bug Tracker中,状态为 Closed + WONTFIX。

我已经修复了它编辑 ConfigParser.py 文件。在 write 方法中(关于第 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 文件。

于 2016-02-01T21:49:59.920 回答
-2

我所做的只是:

file_name = file_name.decode("utf-8")
cfg.read(file_name)
于 2018-10-11T14:53:43.810 回答