2012-08-06 51 views
4

我想用StringIO來提供ConfigObj。 我想在我的單元測試中做到這一點,這樣我就可以動態配置「文件」,這取決於我想要在配置對象中測試什麼。 (我正在閱讀幾個conf文件,爲其他應用程序聚合和「格式化」信息)。我有一大堆我在配置模塊中照顧的東西。但是,在測試中,我面臨來自地獄的統一碼錯誤。我想我已經將我的問題固定在最小函數代碼上,我已經提取並簡化了這個問題的目的。使用StringIO for ConfigObj和Unicode

我做如下:

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

import configobj 
import io 

def main(): 
    """Main stuff""" 

    input_config = """ 
    [Header] 
    author = PloucPlouc 
    description = Test config 

    [Study] 
    name_of_study = Testing 
    version = 9999 
    """ 

    # Just not to trust my default encoding 
    input_config = unicode(input_config, "utf-8") 

    test_config_fileio = io.StringIO(input_config)  
    print configobj.ConfigObj(infile=test_config_fileio, encoding="UTF8") 

if __name__ == "__main__": 
    main() 

它產生以下回溯:

Traceback (most recent call last): 
File "test_configobj.py", line 101, in <module> 
    main() 
File "test_configobj.py", line 98, in main 
    print configobj.ConfigObj(infile=test_config_fileio, encoding='UTF8') 
File "/work/irlin168_1/USER/Apps/python272/lib/python2.7/site-packages/configobj-4.7.2-py2.7.egg/configobj.py", line 1242, in __init__ 
    self._load(infile, configspec) 
File "/work/irlin168_1/USER/Apps/python272/lib/python2.7/site-packages/configobj-4.7.2-py2.7.egg/configobj.py", line 1302, in _load 
    infile = self._handle_bom(infile) 
File "/work/irlin168_1/USER/Apps/python272/lib/python2.7/site-packages/configobj-4.7.2-py2.7.egg/configobj.py", line 1442, in _handle_bom 
    if not line.startswith(BOM): 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xef in position 0: ordinal not in range(128) 

我使用Python的2.7.2(32位)上的Linux。我的控制檯和編輯器(Kile)的語言環境設置爲fr_FR.utf8。

我想我可以做到這一點。

io.StringIO documentation,我得到這個:

的StringIO對象可以接受Unicode或8位字符串,但混合兩種可能需要一些照顧。

而且從ConfigObj documentation,我可以這樣做:

>>> config = ConfigObj('config.ini', encoding='UTF8') 
>>> config['name'] 
    u'Michael Foord' 

this

INFILE:無

你並不需要指定一個INFILE。如果你忽略它,將會創建一個空的ConfigObj。 INFILE可以是:

[...] 
    A StringIO instance or file object, or any object with a read method. The filename attribute of your ConfigObj will be None [5]. 

'編碼':無

默認ConfigObj文件/字符串傳遞給它不解碼成Unicode [8]。如果你想要你的配置文件爲Unicode(鍵和成員),你需要提供一個編碼來解碼文件。編碼時也將使用此編碼對配置文件進行編碼。

我的問題是爲什麼產生這個?還有什麼?我纔不從(簡單)統一處理明白...

通過看這個answer,我改變了:

input_config = unicode(input_config, "utf8") 

到(進口編解碼器模塊breforehand):

input_config = unicode(input_config, "utf8").strip(codecs.BOM_UTF8.decode("utf8", "strict")) 

爲了擺脫可能包含的字節順序標記,但它沒有幫助。

非常感謝

注:我也有同樣回溯如果我使用StringIO.StringIO代替io.StringIO。

回答

3

這條線:

input_config = unicode(input_config, "utf8") 

是您的輸入轉換爲Unicode,但此行:

print configobj.ConfigObj(infile=test_config_fileio, encoding="UTF8") 

被宣佈該輸入是一個UTF-8編碼的字節串。該錯誤表示在預期字節字符串時傳遞了Unicode字符串,因此註釋掉上面的第一行應該可以解決問題。我目前沒有configobj,所以無法測試。

+0

感謝您的回答。併爲錯誤進行啓發。但是,io.StringIO期望將Unicode作爲輸入。如果我將字符串input_config聲明爲unicode(使用input_config = u「」「blablabla」「」),並刪除你提到的那一行,我有同樣的錯誤。但是,通過閱讀:http://stackoverflow.com/a/3423935/493211,將'import io'更改爲'從io將BytesIO作爲StringIO'導入,並使用input_config作爲字節字符串,然後一切正常......如果我實際上使用StringIO(而不是io.StringIO)和一個字節字符串... – 2012-08-06 20:33:02

+0

啊!錯過了這個細節,正在考慮舊的'StringIO.StringIO'(與'io.BytesIO'相同)。很高興你找到解決方案! – 2012-08-07 04:37:46