PythonでのUTF8 CSVファイルの読み取り


93

Pythonでアクセント付き文字を含むCSVファイルを読み込もうとしています(フランス語および/またはスペイン語の文字のみ)。csvreaderのPython 2.5ドキュメント(http://docs.python.org/library/csv.html)に基づいて、csvreaderはASCIIのみをサポートしているため、CSVファイルを読み取るために次のコードを考え出しました。

def unicode_csv_reader(unicode_csv_data, dialect=csv.excel, **kwargs):
    # csv.py doesn't do Unicode; encode temporarily as UTF-8:
    csv_reader = csv.reader(utf_8_encoder(unicode_csv_data),
                            dialect=dialect, **kwargs)
    for row in csv_reader:
        # decode UTF-8 back to Unicode, cell by cell:
        yield [unicode(cell, 'utf-8') for cell in row]

def utf_8_encoder(unicode_csv_data):
    for line in unicode_csv_data:
        yield line.encode('utf-8')

filename = 'output.csv'
reader = unicode_csv_reader(open(filename))
try:
    products = []
    for field1, field2, field3 in reader:
        ...

以下は、私が読み込もうとしているCSVファイルの抜粋です。

0665000FS10120684,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Bleu
0665000FS10120689,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Gris
0665000FS10120687,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Vert
...

UTF-8へのエンコード/デコードを試みても、次の例外が発生します。

Traceback (most recent call last):
  File ".\Test.py", line 53, in <module>
    for field1, field2, field3 in reader:
  File ".\Test.py", line 40, in unicode_csv_reader
    for row in csv_reader:
  File ".\Test.py", line 46, in utf_8_encoder
    yield line.encode('utf-8', 'ignore')
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 68: ordinal not in range(128)

どうすれば修正できますか?


マーティン、あなたが周りにいるなら、あなたはマーテリのPython 2のみの答えから受け入れられた答えを切り替えることを検討しますか?
Antti Haapala 2016

回答:


113

この.encodeメソッドはUnicode文字列に適用され、バイト文字列を作成します。しかし、代わりにバイト文字列で呼び出しています...間違った方法「ラウンド!見てくださいcodecs標準ライブラリ内のモジュールとcodecs.openUTF-8エンコードされたテキストファイルを読み込むためのより良い一般的なソリューションのために特に。ただし、csv特にモジュールの場合は、utf-8データを渡す必要があります。これは既に取得していることなので、コードははるかに単純になります。

import csv

def unicode_csv_reader(utf8_data, dialect=csv.excel, **kwargs):
    csv_reader = csv.reader(utf8_data, dialect=dialect, **kwargs)
    for row in csv_reader:
        yield [unicode(cell, 'utf-8') for cell in row]

filename = 'da.csv'
reader = unicode_csv_reader(open(filename))
for field1, field2, field3 in reader:
  print field1, field2, field3 

PS:入力データがutf-8ではなく、たとえばISO-8859-1であることが判明した場合は、「トランスコーディング」が必要です(csvモジュールレベルでutf-8を使いたい場合)。 、の形式line.decode('whateverweirdcodec').encode('utf-8')ですが、ISO-8859- *エンコードされたバイト文字列では実際には問題ないので、yield上記のコードの行では、既存のエンコーディングの名前をの代わりに使用できます。'utf-8'csv


4
これは、Pythonドキュメント(OPのコピーと貼り付け元)の例が間違っていることを意味しますか?あなたがそれにUnicode csvを与えたときにそれが壊れた場合にそれが行う追加のエンコーディングステップのポイントは何ですか?
エントロピー:2014年


80

Python 2.X

問題を解決するunicode-csvライブラリがあり、新しいcsv関連のコードを書く必要がないという利点があります。

以下は、readmeの例です。

>>> import unicodecsv
>>> from cStringIO import StringIO
>>> f = StringIO()
>>> w = unicodecsv.writer(f, encoding='utf-8')
>>> w.writerow((u'é', u'ñ'))
>>> f.seek(0)
>>> r = unicodecsv.reader(f, encoding='utf-8')
>>> row = r.next()
>>> print row[0], row[1]
é ñ

Python 3.X

Python 3では、これは組み込みcsvモジュールによってそのままサポートされます。この例を見てください:

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

8

utf-8でエンコードされたCSVファイルを読み取りたい場合は、次のようなものを使用することをお勧めします。

with open(file_name, encoding="utf8") as csv_file:

そのステートメントを使用すると、後でCSVリーダーを使用して作業できます。


2
これがPython 3のみである可能性はありますか?これは、Python 2にそれは受け入れていない、私のために失敗したencodingopen
Zvika

@Zvikaはい、Python 3ではこのソリューションが機能します:open('file.csv', 'r', encoding="ISO8859")
luca76

また、open(file_name、 "rt"、encoding = 'utf-8')を追加します。つまり、ファイルを「テキストの読み取り」モードで開きます
Jimmy Lee Jones

3

また、この投稿の回答を確認してくださいhttps : //stackoverflow.com/a/9347871/1338557

ucsv.pyというライブラリの使用を提案しています。Python 2.7のエンコーディングの問題(utf-8)に対処するために書かれたCSVの短くて単純な置き換え。csv.DictReaderのサポートも提供します

編集:私が使用したサンプルコードを追加します:

import ucsv as csv

#Read CSV file containing the right tags to produce
fileObj = open('awol_title_strings.csv', 'rb')
dictReader = csv.DictReader(fileObj, fieldnames = ['titles', 'tags'], delimiter = ',', quotechar = '"')
#Build a dictionary from the CSV file-> {<string>:<tags to produce>}
titleStringsDict = dict()
for row in dictReader:
    titleStringsDict.update({unicode(row['titles']):unicode(row['tags'])})

リンクが壊れた場合に備えて、そのリンクの詳細を回答に含める必要があります\
Yaje

#Downvoter-なぜ役に立たないと思ったのかわからない。ucsvライブラリは私にとってはうまくいきました。2日以来苦労していたunicdeエラーの解決に役立ちました。いくつかのサンプルコードを探していた場合は、ここで編集します@ Yaje-詳細をいくつか示しました。サンプルコードも。リンクも修正しました。以前は他の投稿を指しています。
Atripavan 2014

テキストファイルをバイナリとして開く特別な理由はありますか?'rb'はバイナリファイルを開くためのものです。
Codeguy007 2018年

2

使用codecs.openアレックスマルテッリは私にとって有用であることが証明された提案されているよう。

import codecs

delimiter = ';'
reader = codecs.open("your_filename.csv", 'r', encoding='utf-8')
for line in reader:
    row = line.split(delimiter)
    # do something with your row ...

3
すべてのCSVでは機能しません。有効なcsv行は次のとおりです: "Foo Bar; Baz"; 231; 313; 「;;;」; 1;
jb。

csvモジュールをインポートしますが、使用しません。
Christophe Roussy

1

ヘルプページへのリンクはpython 2.6でも同じですが、私の知る限り、2.5からのcsvモジュールの変更はありません(バグ修正以外)。以下は、エンコード/デコードを行わなくても機能するコードです(ファイルda.csvには、変数dataと同じデータが含まれています)。私はあなたのファイルが変換なしで正しく読まれるべきだと思います。

test.py:

## -*- coding: utf-8 -*-
#
# NOTE: this first line is important for the version b) read from a string(unicode) variable
#

import csv

data = \
"""0665000FS10120684,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Bleu
0665000FS10120689,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Gris
0665000FS10120687,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Vert"""

# a) read from a file
print 'reading from a file:'
for (f1, f2, f3) in csv.reader(open('da.csv'), dialect=csv.excel):
    print (f1, f2, f3)

# b) read from a string(unicode) variable
print 'reading from a list of strings:'
reader = csv.reader(data.split('\n'), dialect=csv.excel)
for (f1, f2, f3) in reader:
    print (f1, f2, f3)

da.csv:

0665000FS10120684,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Bleu
0665000FS10120689,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Gris
0665000FS10120687,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Vert

これはどのバージョンのpythonで動作しますか?2.7と3.5の両方でエラーが発生します。「ValueError:アンパックするのに十分な値ではありません(期待される3、得られた1)」
eis

@eis:あなたのシステムではコンマがデフォルトの区切り文字ではないと想像できます。のdelimiter=','代わりに追加してみてくださいdialect=csv.excel
バン

1

何もうまくいかなければ、あなたは自分の道を逃れるのを忘れているかもしれないことに注意する価値があります。
たとえば、次のコード:

f = open("C:\Some\Path\To\file.csv")

エラーになります:

SyntaxError:(unicode error) 'unicodeescape' codec ca n't cannot bytes in position 2-3:truncated \ UXXXXXXXX escape

修正するには、次のようにします。

f = open("C:\\Some\\Path\\To\\file.csv")

0

見るとLatin-1Unicodeのテーブル、私は、文字コードを参照00E9LATIN SMALL LETTER E WITH ACUTEを」。これは、サンプルデータのアクセント付き文字です。の簡単なテストは、この文字のエンコーディングがunicode(ほぼ)エンコーディングとは異なるPythonことUTF-8を示していUTF-16ます。

>>> u'\u00e9'
u'\xe9'
>>> u'\u00e9'.encode('utf-8')
'\xc3\xa9'
>>> 

encode("UTF-8")specialを呼び出す前に、Unicodeデータを試すことをお勧めしますunicode_csv_reader()。ファイルからデータを単に読み取るだけではエンコードが隠される可能性があるため、実際の文字値を確認してください。


0

別のサーバーでも同じ問題がありましたが、ロケールが混乱していることがわかりました。

export LC_ALL="en_US.UTF-8"

問題を修正しました

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.