2009-10-30 92 views
17

我的ConfigParser問題仍在繼續。它似乎不太支持Unicode。配置文件確實保存爲UTF-8,但是當ConfigParser讀取它時,它似乎被編碼爲其他內容。我以爲這是Latin-1的和我thougt覆蓋optionxform可以幫助:帶有Unicode項目的ConfigParser

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

我已經嘗試了幾個不同的變化解碼',但這一點似乎沒有意義,因爲它從一開始就應該是一個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()

+0

雪人不是'拉丁1' – u0b34a0f6ae 2009-10-30 13:23:17

+0

永遠不要做'除了Exception'一部分;趕上你知道如何處理的實際例外。 – 2010-03-23 07:51:55

回答

19

ConfigParser.readfp()方法可以採取一個文件對象,你試圖與正確的編碼使用的編解碼器模塊將其發送到ConfigParser像下面之前打開文件對象:

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

對於Python 3.2或以上,readfp()已棄用。改爲使用read_file()

+1

我有同樣的問題,並解決它從配置文件中讀取相同的方式。但我還需要重寫它的修改版本,即使我使用codecs.open:'codecs.open(filename,encoding = ENCODING,mode ='wb')作爲conffile:config.write(conffile) ' – 2011-04-04 16:16:39

+0

嗨Ghislain,我有與configparser寫回unicode字符串相同的問題。它通過點更新到最新版本來解決。 – Erxin 2013-05-14 06:15:45

1

配置模塊在讀取和寫入unicode字符串時被破壞。我試圖修復它,但卻被解析器的奇怪方式所困擾。

1

似乎是用於python 2x的ConfigParser版本的問題,並且3x版本沒有此問題。在this issue of the 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文件。

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

您也可以對RawConfigParser進行猴子修補:'RawConfigParser.write = write' – 2017-07-26 18:05:51