2013-03-14 1 views
6

그래서 JSON 파일을 탭 구분 파일로 구문 분석하려고합니다. 구문 분석이 제대로 작동하고 모든 데이터가 통과하는 것 같습니다. 가장 이상한 일이 출력 파일에서 일어나고 있지만. 탭 구분 기호를 사용하고 출력에 탭을 사용한다고했지만 여전히 작은 따옴표를 사용하는 것으로 보입니다. 웬일인지 문자 B를 처음에 추가하는 것 같습니다. 필자는 수동으로 헤더를 입력했는데 제대로 작동하지만 데이터 자체가 이상하게 작동합니다. 다음은 내가 얻는 결과의 예입니다.파이썬 CSV 작성기가 각 요소의 시작 부분에 문자를 추가하고 인코딩 문제가 발생했습니다

id created text screen name name latitude longitude place name place type 
b'1234567890' b'Thu Mar 14 19:39:07 +0000 2013' "b""I'm at Bank Of America (Wayne, MI) http://t.co/asdf""" b'userid' b'username' 42.28286837 -83.38487864 b'Bank Of America, Wayne' b'poi' 
b'1234567891' b'Thu Mar 14 19:39:16 +0000 2013' b'here is a sample tweet \xf0\x9f\x8f\x80 #notingoodhands' b'userid2' b'username2' 

다음은 데이터를 쓰는 데 사용하는 코드입니다.

out = open(filename, 'w') 
    out.write('id\tcreated\ttext\tscreen name\tname\tlatitude\tlongitude\tplace name\tplace type') 
    out.write('\n') 
    rows = zip(ids, times, texts, screen_names, names, lats, lons, place_names, place_types) 
    from csv import writer 
    csv = writer(out, dialect='excel', delimiter = '\t') 
    for row in rows: 
     values = [(value.encode('utf-8') if hasattr(value, 'encode') else value) for value in row] 
     csv.writerow(values) 
    out.close() 

그래서 여기 있습니다. 만약 내가 utf-8 비트없이 이것을하고 곧바로 출력한다면, 포맷팅은 내가 원하는 방식으로 완벽하게 될 것이다. 그러나 사람들이 특수 문자를 입력하면 프로그램이 충돌하고 처리 할 수 ​​없습니다.

Traceback (most recent call last): 
    File "tweets.py", line 34, in <module> 
    csv.writerow(values) 
    File "C:\Python33\lib\encodings\cp1252.py", line 19, in encode 
    return codecs.charmap_encode(input,self.errors,encoding_table)[0] 
UnicodeEncodeError: 'charmap' codec can't encode character '\U0001f3c0' in position 153: character maps to <undefined> 

utf-8 비트를 추가하면 여기에 표시되는 출력 유형으로 변환되지만 출력에이 모든 문자가 추가됩니다. 아무도 이것에 어떤 생각을 가지고 있습니까?

답변

6

데이터를 직접 인코딩하기 때문에 유니 코드 대신 바이트 데이터를 파일에 쓰고 있습니다.

encode 호출을 모두 제거하고 파이썬이이 문제를 처리하도록하십시오. 파일이됩니다 읽기 위해 CSV 파일을 여는 데 사용되는 open() 이후

다음 UTF8 인코딩 파일을 열고 나머지는 자체 처리한다 :

out = open(filename, 'w', encoding='utf8') 

이것은 csv module documentation에 설명되어 기본적으로 시스템 기본 인코딩을 사용하여 유니 코드로 디코딩됩니다 (locale.getpreferredencoding() 참조). 시스템 기본 인코딩이 아닌 다른 뭔가를 작성하는

import csv 
with open('some.csv', newline='', encoding='utf-8') as f: 
    reader = csv.reader(f) 
    for row in reader: 
     print(row) 

동일하게 적용 : 다른 인코딩을 사용하여 파일을 디코딩하려면 열기의 인코딩 인수를 사용하여 출력 파일을 열 때 인코딩 인수를 지정합니다.

+0

그 트릭을했습니다. 감사! – brian

0

여기에 여러 가지가 있지만 우선 약간의 혼란을 정리해 보겠습니다.

비 ASCII 문자를 UTF-8로 인코딩하면 여러 바이트를 얻게됩니다. 예를 들어 문자 은 UTF-8에서 \xf0\x9f\x8f\x80입니다. 그러나 그것은 여전히 ​​하나의 문자입니다, 그것은 4 바이트를 차지하는 문자 일뿐입니다. 문자열을 이진 파일에 쓴 다음 UTF-8 호환 도구 (메모장 또는 텍스트 편집기 또는 UTF-8 친화적 인 터미널/셸의 cat)에서 해당 파일을 보면 , 쓰레기 4 개가 아닙니다.

두 번째로 b'abc'은 처음에 b이 추가 된 문자열이 아니며, abcrepr 표현입니다. b은 따옴표보다 더 이상 문자열의 일부가 아닙니다.

마지막으로 Python 3에서는 파일을 텍스트 모드로 열고 바이트 문자열을 쓸 수 없습니다.텍스트 모드로 인코딩을 열고 일반 유니 코드 문자열을 쓰거나 바이너리 모드로 열고 인코딩 된 바이트 문자열을 작성하십시오.

관련 문제