2013-03-14 8 views
6

したがって、JSONファイルをタブ区切りファイルに解析しようとしています。解析はうまくいくように見え、すべてのデータが通過しています。出力ファイルでは奇妙なことが起こっていますが。私はタブデリミタを使用するように指示しました。出力にはタブを使用していましたが、依然として一重引用符を保持しているようです。何らかの理由で、文字Bを最初に追加しているようです。私は手動でヘッダーに入力し、それは正常に動作しますが、データ自体は変な動作をしています。ここに私が得ている出力の例があります。Python 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の呼び出しをすべて削除し、Pythonでこれを処理させます。 UTF8エンコーディングでファイルを開き、残りは自分自身の面倒を見る:

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

これはcsv module documentationで文書化されています

open()が読み取り用のCSVファイルを開くために使用されているので、ファイルがしますデフォルトでは、システムのデフォルトエンコーディング(locale.getpreferredencoding()を参照)を使用して、Unicodeにデコードされます。システムのデフォルトエンコーディング以外の何かに書くことに

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です。しかしそれはまだ1文字ですが、それはちょうど4バイトを要する文字です。文字列をバイナリファイルに書き込んだり、そのファイルをUTF-8互換ツール(メモ帳やテキストエディット、またはUTF-8に適した端末/シェルのcat)で見ると、と表示されます。 4つのガベージ文字ではありません。

第2に、b'abc'は先頭にbが追加された文字列ではなく、abcrepr表現です。 bは引用符よりも文字列の一部ではありません。

最後に、Python 3では、ファイルをテキストモードで開き、バイト文字列を書き込むことはできません。テキストモードでエンコードして開き、通常のユニコード文字列を書き込むか、バイナリモードで開き、エンコードされたバイト文字列を書き込んでください。

関連する問題