2012-12-14 1 views
1

Существует множество тем по этой проблеме в Интернете, но я не могу найти ответ для моего конкретного случая.Python CSV-файл UTF-16 для UTF-8 Ошибка печати

У меня есть файл CSV. Я не уверен, что это было сделано для него, но когда я пытаюсь открыть его, я получаю:

UnicodeDecodeError: 'utf8' codec can't decode byte 0xff in position 0: invalid start byte

Вот полный Traceback:

Traceback (most recent call last): 
    File "keywords.py", line 31, in <module> 
    main() 
    File "keywords.py", line 28, in main 
    get_csv(file_full_path) 
    File "keywords.py", line 19, in get_csv 
    for row in reader: 
UnicodeEncodeError: 'ascii' codec can't encode character u'\u5a07' in position 10: ordinal not in range(128) 

С помощью переполнения стека, я получил его открыть с:

reader = csv.reader(codecs.open(file_full_path, 'rU', 'UTF-16'), delimiter='\t', quotechar='"')

Теперь проблема заключается в том, что, когда я читаю файл:

def get_csv(file_full_path): 
    import csv, codecs 
    reader = csv.reader(codecs.open(file_full_path, 'rU', 'UTF-16'), delimiter='\t', quotechar='"') 
    for row in reader: 
     print row 

я застревают на азиатских символов:

UnicodeEncodeError: 'ascii' codec can't encode character u'\u5a07' in position 10: ordinal not in range(128)

Я попытался decode, «закодировать», unicode() на строку, содержащую этот символ, но это не кажется помощь.

for row in reader: 
    #decoded_row = [element_s.decode('UTF-8') for element_s in row] 
    #print decoded_row 
    encoded_row = [element_s.encode('UTF-8') for element_s in row] 
    print encoded_row 

На данный момент я не совсем понимаю, почему. Если я

>>> print u'\u5a07' 
娇 

или

>>> print '娇' 
娇 

это работает. Также в терминале он также работает. Я проверил по умолчанию кодировку на терминале и оболочку Python, это UTF-8 во всем мире. И он легко печатает этот символ. Я предполагаю, что это имеет какое-то отношение ко мне, открывая файл с codecs с использованием UTF-16.

Я не уверен, куда идти отсюда. Может ли кто-нибудь помочь?

+0

Пожалуйста, покажите нам * полный * след вашего исключения, а также соответствующий раздел кода. –

+0

Вы также должны прочитать [Python Unicode HOWTO] (http://docs.python.org/2/howto/unicode.html), чтобы понять, когда и где Python может автоматически пытаться * кодировать * unicode. –

+0

Из документации модуля 'csv': * Эта версия модуля csv не поддерживает ввод Unicode. Кроме того, в настоящее время существуют некоторые проблемы, связанные с символами NULL ASCII. Соответственно, все входные данные должны быть UTF-8 или ASCII для печати, чтобы быть в безопасности *. –

ответ

3

csv модуль не может ручка ввода Unicode.Он говорит, что так конкретно на его documentation page:

Note: This version of the csv module doesn’t support Unicode input. Also, there are currently some issues regarding ASCII NUL characters. Accordingly, all input should be UTF-8 or printable ASCII to be safe;

Вам необходимо преобразовать файл CSV в UTF-8, так что модуль может иметь дело с этим:

with codecs.open(file_full_path, 'rU', 'UTF-16') as infile: 
    with open(file_full_path + '.utf8', 'wb') as outfile: 
     for line in infile: 
      outfile.write(line.encode('utf8')) 

В качестве альтернативы, вы можете использовать Command- лайн утилиту iconv, чтобы преобразовать файл для вас.

Затем используйте этот перекодируются файл для чтения данных:

reader = csv.reader(open(file_full_path + '.utf8', 'rb'), delimiter='\t', quotechar='"') 
for row in reader: 
    print [c.decode('utf8') for c in row] 

Обратите внимание, что столбцы, то нужно декодирование в юникод вручную.

+0

работал как шарм! он не только решил проблему, но и расширил мое понимание кодирования в python. Большое спасибо. – Katafalkas

-1

Кодировать ошибки - это то, что вы получаете, когда пытаетесь преобразовать символы Unicode в 8-битные последовательности. Поэтому ваша первая ошибка не является ошибкой, когда на самом деле читает файл, но чуть позже.

Вероятно, вы получите эту ошибку, потому что модуль Python 2 CSV ожидает, что файлы будут в двоичном режиме, тогда как вы открыли его, чтобы он возвращал строки Unicode.

Изменение открытия этого:

reader = csv.reader(open(file_full_path, 'rb'), delimiter='\t', quotechar='"') 

И вы должны быть хорошо. Или еще лучше:

with open(file_full_path, 'rb') as infile: 
    reader = csv.reader(infile, delimiter='\t', quotechar='"') 
    # CVS handling here. 

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

+0

Нет, это не сработает, потому что файл не является UTF-8 или ASCII. Модуль 'csv' * не может обрабатывать вход * UTF-16. Он не знает, как работать с 2 байтами на символ. Фактически, ОП уже заявил, что они пытались открыть CSV-файл так, как вы предлагаете здесь. :-) –

+0

@MartijnPieters: Ах, пенни просто упал. Да, это урезает каждое значение неправильно. Я не вижу, что он заявил, что он попытался открыть его вот так. –

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