Чтение файла CSV UTF8 с помощью Python
Я пытаюсь прочитать CSV-файл с акцентированными символами с Python (только французские и/или испанские символы). На основе документации Python 2.5 для csvreader (http://docs.python.org/library/csv.html), я придумал следующий код для чтения CSV-файла, так как csvreader поддерживает только ASCII.
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)
как это исправить?
7 ответов:
The
.encodeметод применяется к строке Юникода, чтобы сделать байт-строку; но вы вызываете его на байт-строку вместо этого... неправильно! Посмотрите наcodecsмодуль в стандартной библиотеке иcodecs.openв частности, для улучшения общих решений для чтения текстовых файлов в кодировке UTF-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, field3PS: Если это оказывается, что ваши входные данные находятся не в utf-8, а, например, в ISO-8859-1, тогда вам нужно "перекодирование" (если вы заинтересованы в использовании utf-8 в
csvуровень модуля), формыline.decode('whateverweirdcodec').encode('utf-8')-- но, вероятно, вы можете просто использовать имя существующей кодировке вyieldстрока в моем коде выше, вместо'utf-8', аcsvна самом деле будет просто отлично с ISO-8859-* закодированные bytestrings.
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)
также проверьте ответ в этом посте: https://stackoverflow.com/a/9347871/1338557
это предполагает использование библиотеки под названием ucsv.py. короткая и простая замена для CSV, написанного для решения проблемы кодирования (utf-8) для Python 2.7. Также предусмотрена поддержка csv.Диктофон
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'])})
используя
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 ...
ссылка на страницу справки одинакова для python 2.6 и, насколько я знаю, не было никаких изменений в модуле csv с 2.5 (кроме исправлений ошибок). Вот код, который просто работает без кодирования / декодирования (файл da.csv содержит те же данные, что и переменная данные). Я предполагаю, что ваш файл должен быть правильно прочитан без каких-либо преобразований.
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)да.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
смотреть на!--9-->
Latin-1таблица Юникод, Я вижу код символа00E9"ЛАТИНСКАЯ СТРОЧНАЯ БУКВА Е С ОСТРЫМ". Это символ с ударением в образце данных. Простой тест вPythonвидно, чтоUTF-8кодировка для этого символа отличается от Юникода (почтиUTF-16) кодирование.>>> u'\u00e9' u'\xe9' >>> u'\u00e9'.encode('utf-8') '\xc3\xa9' >>>Я предлагаю вам попробовать
encode("UTF-8")данные unicode перед вызовом специальногоunicode_csv_reader(). Простое чтение данных из файла может скрыть кодировка, поэтому проверьте фактические значения символов.
Если вы хотите прочитать CSV-файл с кодировкой utf-8, минималистичный подход, который я рекомендую вам использовать что-то вроде этого:
with open(file_name, encoding="utf8") as csv_file:С этим утверждением вы можете использовать позже читатель CSV для работы.
Comments