2012-08-06 3 views
4

StringIO를 사용하여 ConfigObj를 공급하려고합니다. 유닛 테스트에서이 작업을 수행하고 싶으므로 구성 오브젝트에서 테스트 할 대상에 따라 설정 "파일"을 즉시 조롱 할 수 있습니다.ConfigObj 및 유니 코드에 StringIO 사용

구성 모듈에서 돌보는 모든 것들이 있습니다. (저는 여러 conf 파일을 읽고 집계하고 나머지 응용 프로그램에 대한 정보를 "서식 지정"합니다). 그러나 테스트에서 유니 코드 오류가 hell에서 발생했습니다. 나는이 문제의 목적을 위해 추출하고 과도하게 단순화 한 최소한의 기능 코드에 내 문제를 고정 시켰다고 생각한다.

#!/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) 

나는 리눅스에서 파이썬 2.7.2 (32 비트)를 사용하고 있습니다. 콘솔 및 편집기 (Kile)에 대한 내 로캘은 fr_FR.utf8로 설정됩니다.

나는 이것을 할 수 있다고 생각했다. io.StringIO documentation에서

, 내가 가지고이 :

있는 StringIO 객체가 유니 코드 또는 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 저가

[8]. 구성 파일을 유니 코드 (키 및 멤버)로 사용하려면 파일을 디코딩 할 인코딩을 제공해야합니다. 이 인코딩은 작성시 구성 파일을 인코딩하는 데에도 사용됩니다.

제 질문은 왜 이것을 생성합니까? ? 내가 처리 (단순) 유니 코드에서 다른 무엇을 이해하지 못했다 ...

을이 answer보고, 나는 변경 :

input_config = unicode(input_config, "utf8") 

(코덱 모듈 breforehand 가져 오기)에 :

input_config = unicode(input_config, "utf8").strip(codecs.BOM_UTF8.decode("utf8", "strict")) 
가능한 한 포함 된 바이트 순서 표시를 없애기 위해

하지만 도움이되지 못했습니다.

덕분에 많은

NB : 나는 대신 io.StringIO의 StringIO.StringIO를 사용하는 경우 나도 같은 역 추적이있다.

답변

3

이 라인 :

input_config = unicode(input_config, "utf8") 

유니 입력을 변환하지만,이 라인은 :
print configobj.ConfigObj(infile=test_config_fileio, encoding="UTF8") 

은 UTF-8 인코딩 바이트 문자열로 입력을 선언한다. 이 오류는 바이트 문자열이 예상 될 때 유니 코드 문자열이 전달되었음을 나타내므로 위의 첫 번째 행을 주석 처리하면 문제가 해결됩니다. 지금은 configobj이 없으므로 테스트 할 수 없습니다.

+0

답변 해 주셔서 감사합니다. 그리고 실수를 확대하기 위해서. 그러나 io.StringIO는 유니 코드를 입력으로 간주합니다. "input_config = u" "" "blablabla" ""를 사용하여 유니 코드로 문자열 input_config를 선언하고 언급 한 행을 제거하면 동일한 오류가 발생합니다. 그러나 이것을 읽으면 : http://stackoverflow.com/a/3423935/493211,'import io'를'io import BytesIO StringIO'로 변경하고 input_config를 바이트 문자열로 사용하면 모든 것이 작동합니다 ... 그것은 또한 실제로 StringIO (및 io.StringIO) 바이트 문자열을 사용하는 경우 작동합니다 ... –

+0

Ah! 세부 사항을 놓치지 않고 오래된'StringIO.StringIO' ('io.BytesIO'와 동일)로 생각했습니다. 다행히 해결책을 찾았습니다! –

관련 문제