2013-08-28 1 views
2

Я читала в файле CSV, который имеет кодировку UTF8:Чтение UTF8 кодируется CSV и преобразование в UTF-16

ifile = open(fname, "r") 
for row in csv.reader(ifile): 
    name = row[0] 
    print repr(row[0]) 

Это прекрасно работает, и печатает то, что я ожидаю, что это распечатать; UTF8 кодируется str:

> '\xc3\x81lvaro Salazar' 
> '\xc3\x89lodie Yung' 
... 

Кроме того, когда я просто напечатать str (в отличие от repr()) Выход отображает нормально (я не понимаю eitherway - не должны это вызовет ошибку?):

> Álvaro Salazar 
> Élodie Yung 

, но когда я пытаюсь преобразовать мой UTF8 кодируются strs в unicode:

ifile = open(fname, "r") 
for row in csv.reader(ifile): 
    name = row[0] 
    print unicode(name, 'utf-8') # or name.decode('utf-8') 

я получаю инф amous:

Traceback (most recent call last):          
File "scripts/script.py", line 33, in <module> 
    print unicode(fullname, 'utf-8') 
UnicodeEncodeError: 'ascii' codec can't encode character u'\xc1' in position 0: ordinal not in range(128) 

Так что я смотрел на юникод строк, которые создаются:

ifile = open(fname, "r") 
for row in csv.reader(ifile): 
    name = row[0] 
    unicode_name = unicode(name, 'utf-8') 
    print repr(unicode_name) 

и выход

> u'\xc1lvaro Salazar' 
> u'\xc9lodie Yung' 

Так что теперь я совершенно запутался, это, кажется, искаженные шестнадцатеричные значения. Я прочитал этот вопрос:

и кажется, что я делаю все правильно, что приводит меня к мысли, что мой файл на самом деле не UTF8, но когда я сначала распечатать repr значений ячеек, они, похоже, исправляют шестнадцатеричные значения UTF8. Может ли кто-либо указать на мою проблему или указать, где мое понимание разваливается (как я начинаю теряться в джунглях кодировок)


Как и в сторону, я полагаю, что я мог бы использовать codecs, чтобы открыть файл и читать его прямо в объекты unicode, но модуль csv не поддерживает юникод изначально, поэтому я могу использовать этот подход.

ответ

5

Ваша кодировка по умолчанию - ASCII. Когда вы пытаетесь распечатать объект unicode, интерпретатор поэтому пытается его кодировать с использованием кодека ASCII, который не работает, потому что ваш текст содержит символы, которые не существуют в ASCII.

Причина, по которой печать закодированного UTF-8 байтовой строки не приводит к ошибке (которая, кажется, путает вас, хотя и не должна) заключается в том, что это просто отправляет байты на ваш терминал. Он никогда не приведет к ошибке Python, хотя может привести к уродливому выводу, если ваш терминал не знает, что делать с байтами.

Чтобы распечатать юникод, используйте print some_unicode.encode('utf-8'). (Или любой кодирующий ваш терминал на самом деле использует).

Что касается u'\xc1lvaro Salazar', ничего здесь не искалечено.Символ Á находится в кодекода Unicode C1 (который не имеет ничего общего с его представлением UTF-8, но имеет то же значение, что и в латинском-1), и Python использует \x hex escapes вместо \u unicode для кодовых точек для кодовых точек что бы 00, как самый старший байт для экономии места (он также мог отображаться это как \u00c1.)

чтобы получить хороший обзор того, как работает Unicode в Python, я предлагаю http://nedbatchelder.com/text/unipain.html

+0

Эй спасибо. Это очень помогло. Это все начало вписываться - как python (и интерпретатор + stdout) управляет unicode и т. Д., Меня сбивает с толку, но я думаю, теперь это ясно. Это видео также отлично. –

Смежные вопросы