문제

Python XLRD 및 CSV 모듈을 사용하여 Excel 스프레드 시트를 CSV로 변환하려고하지만 인코딩 문제에 매달려 있습니다. XLRD는 유니 코드에서 Excel에서 출력을 생성하고 CSV 모듈에는 UTF-8이 필요합니다.

나는 이것이 XLRD 모듈과 관련이 없다는 것을 이미징한다.

워크 시트는 UTF-16-LE로 인코딩됩니다 book.encoding

내가하는 일의 단순화 된 버전은 다음과 같습니다.

from xlrd import *
import csv
b = open_workbook('file.xls')
s = b.sheet_by_name('Export')
bc = open('file.csv','w')
bcw = csv.writer(bc,csv.excel,b.encoding)
for row in range(s.nrows):
    this_row = []
    for col in range(s.ncols):
        this_row.append(s.cell_value(row,col))
    bcw.writerow(this_row)

이렇게하면 다음과 같은 오류가 약 740 줄을 생성합니다.

UnicodeEncodeError: 'ascii' codec can't encode character u'\xed' in position 5: ordinal not in range(128)

값이 매달려있는 것 같습니다.

나는 캐릭터 인코딩이 어떻게 작동하는지에 대한 모호한 감각 만 있다는 것을 인정할 것입니다. .encode 그리고 .decodes.cell_value(row,col)

누군가가 솔루션을 제안 할 수 있다면, 나는 당신이 작동하지 않는 것과 이유에 대한 설명을 제공 할 수 있다면, 앞으로이 문제들을 더 쉽게 디버깅 할 수 있도록 더 좋을 것입니다.

미리 감사드립니다!

편집하다:

지금까지 의견을 보내 주셔서 감사합니다.

내가 사용자 일 때 this_row.append(s.cell(row,col)) (s.cell_value 대신 egscell) 전체 문서는 오류없이 씁니다.

출력이 특히 바람직하지 않습니다 (text:u'516-7773167'), 그러나 불쾌한 캐릭터가 여전히 출력에 있어도 오류를 피합니다.

이것은 결국 도전이 XLRD에있을 것이라고 생각하게한다.

생각?

도움이 되었습니까?

해결책

나는 기대한다 cell_value 반환 값은 문제를주는 유니 코드 문자열입니다 (인쇄하십시오 type() 이를 확인하려면)이 경우이 한 줄을 변경하여 해결할 수 있어야합니다.

this_row.append(s.cell_value(row,col))

에게:

this_row.append(s.cell_value(row,col).encode('utf8'))

만약에 cell_value 여러 다른 유형을 반환하고 있으면 유니 코드 문자열을 반환하는 경우에만 인코딩해야합니다. 따라서이 줄은 몇 줄로 나뉩니다.

val = s.cell_value(row, col)
if isinstance(val, unicode):
    val = val.encode('utf8')
this_row.append(val)

다른 팁

설명을 요청했지만 일부 현상은 도움 없이는 설명 할 수 없습니다.

(a) Excel 97 이후에 생성 된 XLS 파일의 문자열은 UTF16LE에서 가능한 경우 LATIN1로 인코딩됩니다. 각 문자열에는 사용 된 것을 알려주는 플래그를 전달합니다. 이전에는 사용자의 "코딩"에 따라 인코딩 된 문자열이 뛰어납니다. 어쨌든 XLRD는 유니 코드 객체를 생성합니다. 파일 인코딩은 XLS 파일이 CodePage를 생략하거나 이에 대한 거짓말을하는 타사 소프트웨어에 의해 생성 된 경우에만 관심이 있습니다. XLRD 문서의 앞쪽 위의 유니 코드 섹션을 참조하십시오.

(b) 설명 할 수없는 현상 :

이 코드 :

bcw = csv.writer(bc,csv.excel,b.encoding)

Python 2.5, 2.6 및 3.1로 다음 오류를 일으 킵니다. TypeError: expected at most 2 arguments, got 3 - 이것은 csv.writer의 문서를 감안할 때 내가 기대하는 것에 관한 것입니다. (1) 아무것도 (2) 방언 또는 (3) 하나 이상의 형식 매개 변수를 기대하고 있습니다. 당신은 그것에 방언을 주었고, CSV.Writer는 인코딩 논증이 없습니다. 어떤 버전의 Python을 사용하고 있습니까? 아니면 실제로 실행 한 스크립트를 복사/붙여 넣지 않았습니까?

(c) Traceback 주변의 설명 할 수없는 현상 및 실제 불쾌한 데이터는 다음과 같습니다.

"the_script.py", line 40, in <module>
this_row.append(str(s.cell_value(row,col)))
UnicodeEncodeError: 'ascii' codec can't encode character u'\xed' in position 5: ordinal not in range(128) 

첫째, 단순화 된 스크립트에 있지 않은 범죄 코드 줄에 str ()가 있습니다. 실제로 실행 한 스크립트를 복사/붙여 넣지 않았습니까? 어쨌든, 당신은 일반적으로 STR을 사용해서는 안됩니다. 당신은 당신의 수레에 완전히 정밀하게 얻지 못할 것입니다. CSV 모듈이 변환하도록하십시오.

둘째, "" "" "값은"516-777316 "이라고 말합니다. 원래 Excel 시트의 텍스트는"516-7773167 "(끝에 7이 7 개)" "" "입니다. - 7이 어떻게 끝나는 지 상상하기 어렵습니다. 문제가있는 데이터가 무엇인지 정확히 알아 내기 위해 이와 같은 것을 사용했습니다.

try:
    str_value = str(s.cell_value(row, col))
except:
    print "row=%d col=%d cell_value=%r" % (row, col, s.cell_value(row, col))
    raise

그 %r은 타이핑에서 당신을 절약합니다 cell_value=%s ... repr(s.cell_value(row, col)) ... repr ()는 귀하의 데이터를 명확하게 표현합니다. 배우십시오. 그걸 써.

"516-777316"에 어떻게 도착 했습니까?

셋째, 오류 메시지는 실제로 오프셋 5에서 유니 코드 문자 u ' xed'에 대해 불평하고 있습니다 (즉, 여섯 번째 문자). u+00ed는 급성이있는 라틴어 작은 문자 I이며 "516-7773167"에는 전혀 그런 것이 없습니다.

넷째, 오류 위치는 움직이는 대상 인 것 같습니다. 솔루션 중 하나에 대한 의견에서 "오류는 BCW.Writerow에 있습니다." 뭐?

(d) 오류 메시지를받은 이유 (str () 포함) : str(a_unicode_object) 유니 코드 객체를 STR 객체로 변환하려고 시도하고 인코딩 정보가 없으면 ASCII를 사용하지만 ASCII 데이터가 아닌 데이터가 있습니다. 객체는 UTF8에서 인코딩 된 CSV 파일을 생성하는 것이지만 단순화 된 스크립트는 UTF8을 언급하지 않습니다.

(e) "" "... S.Cell (Row, Col)) (대신 egscell s.cell_value) 전체 문서는 오류없이 씁니다. 출력은 특히 바람직하지 않습니다 (텍스트 : U'516-7773167 ') "" ""

CSV 작가가 __str__ 셀 객체의 방법과 이것은 생성됩니다 <type>:<repr(value)> 디버깅에 유용 할 수 있지만 CSV 파일에서는 그리 좋지 않습니다.

(f) Alex Martelli의 솔루션은 당신이 가게된다는 점에서 훌륭합니다. 그러나 XLRD 문서의 셀 클래스 섹션을 읽어야합니다. 셀 유형은 텍스트, 번호, 부울, 날짜, 오류, 빈 및 빈입니다. 날짜가 있다면 날짜를 숫자가 아닌 날짜로 포맷하려면 isinstance ()를 사용할 수 없습니다 (어쨌든 기능을 호출하는 기능을 원하지 않을 수도 있습니다) ... 이것이 바로 Cell.ctype 속성 및 Sheet.cell_type() 그리고 Sheet.row_types() 방법은 용입니다.

(g) UTF8은 유니 코드가 아닙니다. UTF16LE는 유니 코드가 아닙니다. UTF16은 유니 코드가 아닙니다.

(h) 추가 읽기 (XLRD 문서 외에) :

http://www.joelonsoftware.com/articles/Unicode.html
http://www.amk.ca/python/howto/unicode

두 가지 문제가있는 것 같습니다.

그 셀에 망쳐 놓은 것이 있습니다 - '7'은 aSCII 범위 내에 있기 때문에 u'x37 '로 인코딩되어야합니다.

더 중요한 것은, 당신이 ascii Codec을 사용할 수 없습니다. 유니 코드로 인코딩하는 데 문제가 있다고 제안합니다. 값을 인코딩하려고한다고 생각합니다. 0xed 그것은 ASCII에서 표현할 수 없지만 유니 코드에서 그것을 대표하려고한다고 말했습니다.

나는 어떤 특정 라인이 문제를 일으키는 지 알아 내기에 충분히 똑똑하지 않습니다. 질문을 편집하여 어떤 줄이 그 오류 메시지를 일으키는지를 알려 주면 조금 더 도움이 될 수 있습니다 (나는 그것이 어느 쪽도 생각합니다. this_row.append(s.cell_value(row,col)) 또는 bcw.writerow(this_row), 그러나 확인해 주셔서 감사합니다).

두 가지 가능성이있는 것 같습니다. 하나는 출력 파일을 올바르게 열지 않았다는 것입니다.

"CSVFile이 파일 객체 인 경우 플랫폼의 'B'플래그를 사용하여 차이를 만드는 것이 좋습니다." ( http://docs.python.org/library/csv.html#module-csv )

문제가되지 않는 경우, 다른 옵션은 Codecs.encodedFile (파일, 입력 [, output [, errors]])을 래퍼로 사용하여 .csv를 출력하는 것입니다.

http://docs.python.org/library/codecs.html#module-codecs

이렇게하면 들어오는 UTF16에서 UTF8로 파일 객체 필터를 가질 수 있습니다. 둘 다 기술적으로 "유니 코드"이지만 인코딩하는 방식은 매우 다릅니다.

이 같은:

rbc = open('file.csv','w')
bc = codecs.EncodedFile(rbc, "UTF16", "UTF8")
bcw = csv.writer(bc,csv.excel)

문제를 올바르게 이해했다고 가정하고 파일에 쓸 때 오류가 발생한다고 가정하면 문제를 해결할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top