web-dev-qa-db-ja.com

Pythonを使用してUTF8 CSVファイルを読み取る

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)

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

86
Martin

.encodeメソッドはUnicode文字列に適用され、バイト文字列を作成します。しかし、代わりにバイト文字列で呼び出しています...間違った方法で 'ラウンド! UTF-8でエンコードされたテキストファイルを読み取るためのより一般的なソリューションについては、標準ライブラリのcodecsモジュールとcodecs.openを参照してください。ただし、特に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では、line.decode('whateverweirdcodec').encode('utf-8')という形式の「トランスコーディング」(csvモジュールレベルでutf-8を使用したい場合)が必要ですが、おそらくyieldは実際にISO-8859- *エンコードで問題ないので、上記のコードのcsv行で既存のエンコードの名前を'utf-8'の代わりに使用できます。バイト文字列。

109
Alex Martelli

Python 2.X

問題を解決する nicode-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)
71
jb.

この投稿の回答もご覧ください: https://stackoverflow.com/a/9347871/1338557

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

Edit:使用したサンプルコードの追加:

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'])})
3
Atripavan

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

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

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

3
Nick Cuevas

Alex Martelliが示唆したように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 ...
2
user1154664

ヘルプページへのリンクは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
1
van

別のサーバーでも同じ問題が発生しましたが、ロケールが混乱していることに気付きました。

export LC_ALL="en_US.UTF-8"

問題を修正しました

0
Piotr Pęczek

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

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

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

0
gimel