Подтвердить что ты не робот

UnicodeEncodeError: кодек 'ascii' не может кодировать символ u '\ xa3'

У меня есть таблица Excel, которую я читаю, в которой содержатся некоторые знаки.

Когда я пытаюсь прочитать его при использовании модуля xlrd, я получаю следующую ошибку:

x = table.cell_value(row, col)
x = x.decode("ISO-8859-1")
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa3' in position 0: ordinal not in range(128)

Если я переписываю это на x.encode('utf-8'), он перестает бросать ошибку, но, к сожалению, когда я затем записываю данные где-то в другом месте (как латинский-1), знаки £ все искажаются.

Как я могу исправить это и правильно прочитать знаки £?

--- UPDATE ---

Некоторые читатели предположили, что мне вообще не нужно его декодировать, или что я могу просто закодировать его на латинском языке 1, когда мне это нужно. Проблема заключается в том, что мне нужно вначале записать данные в CSV файл, и, похоже, он обращается к необработанным строкам.

Если я вообще не кодирую или не декодирую данные, это происходит (после того, как я добавил строку в массив, называемый элементами):

for item in items:
    #item = [x.encode('latin-1') for x in item]
    cleancsv.writerow(item)
File "clean_up_barnet.py", line 104, in <module>
 cleancsv.writerow(item)
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2022' in position 43: ordinal not in range(128)

Я получаю ту же ошибку, даже если я раскомментирую строку Latin-1.

4b9b3361

Ответ 1

В вашем фрагменте кода x.decode, но вы получаете ошибку encode - значение x уже есть Unicode, поэтому, чтобы "декодировать" его, он должен быть сначала преобразован в строка байтов (и то, где появляется кодек ansi по умолчанию). В вашем тексте вы скажете "если я переписал ot на x. encode"... что, по-видимому, означает, что вы do знаете, что x является Unicode.

Итак, что вы делаете - и что вам нужно означает - кодирование unicode x, чтобы получить закодированную строку байтов или декодировать строку байтов в объект unicode?

Мне посчастливилось называть encode в байтовой строке и decode на объекте unicode, потому что я считаю, что это приводит к тому, что пользователи не приводят к путанице... но по крайней мере в этом случае вы похоже, удается распространять путаницу (по крайней мере, для меня; -).

Если, как кажется, x является unicode, вы никогда не захотите его "декодировать" - вы можете закодировать его, чтобы получить строку байта с определенным кодеком, например. latin-1, если это то, что вам нужно для каких-то целей ввода-вывода (для использования вашей собственной внутренней программы я рекомендую постоянно придерживаться unicode - только кодировать/декодировать, если и когда вам абсолютно нужна или получать, закодированные строки байтов для ввода/вывода).

Ответ 2

Очень простой способ обойти все кодеки "ascii" не может кодировать символ... "Проблемы с csvwriter состоят в том, чтобы вместо этого использовать unicodecsv, замена для csvwriter.

Установите unicodecsv с помощью pip, а затем вы можете использовать его точно так же, например:

import unicodecsv
file = open('users.csv', 'w')
w = unicodecsv.writer(file)
for user in User.objects.all().values_list('first_name', 'last_name', 'email', 'last_login'):
    w.writerow(user)

Ответ 3

Для чего это стоит: я автор xlrd.

Создает ли xlrd unicode?
Вариант 1. Прочитайте раздел Юникод в нижней части первого экрана xlrd doc: Этот модуль представляет все текстовые строки как объекты юникода Python.
Вариант 2: print type(text), repr(text)

Вы говорите "Если я переписываю это на x.encode(" utf-8 "), он перестает бросать ошибку, но, к сожалению, когда я затем записываю данные где-то еще (как латинский-1), знаки £ все обрушились"." Конечно, если вы напишете текст с кодировкой UTF-8 на устройство, ожидающее latin1, оно будет искажено. Что вы ожидали?

Вы говорите в своем правлении: "" Я получаю ту же ошибку, даже если я раскомментирую латинскую линию 1 "" ". Это очень маловероятно - гораздо вероятнее, что вы получили немного другую ошибку (упоминание кодека latin1 вместо кодека ascii) в другой исходной строке (раскоментированная строка latin1 вместо строки writow). Чтение сообщений об ошибках тщательно помогает пониманию.

Ваша проблема заключается в том, что в целом ваши данные НЕ кодируются в latin1; очень мало реальных данных. Ваш ЗНАК ЗВУКА кодируется в latin1, но это не все ваши данные, отличные от ASCII. Проблематичным является U + 2022 BULLET, который не кодируется в latin1.

Это помогло бы вам получить лучший ответ раньше, если бы вы упомянули фронт, что вы работаете в Mac OS X... обычным подозреваемым для CSV-подходящей кодировки является cp1252 (Windows), а не mac-roman.

Ответ 4

x = x.decode("ISO-8859-1")
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa3' in position 0: ordinal not in range(128)

Посмотрите внимательно: вы получили Unicode *** Encode *** Ошибка при вызове метода декодирования.

Причиной этого является то, что decode предназначен для преобразования из байтовой последовательности (str) в объект unicode. Но, как сказал Джон, xlrd уже использует строки Unicode, поэтому x уже является объектом unicode.

В этой ситуации Python 2.x предполагает, что вы хотели декодировать объект str, поэтому он "помогает" создает его для вас. Но для преобразования a unicode в str ему нужна кодировка и выбирает ASCII, потому что это самый низкий общий знаменатель кодировок символов. Ваш код эффективно интерпретируется как

x = x.encode('ascii').decode("ISO-8859-1")

который терпит неудачу, потому что x содержит символ не ASCII.

Так как x уже является объектом unicode, то decode не требуется. Однако теперь вы столкнулись с проблемой, что модуль Python 2.x csv не поддерживает Unicode. Вы должны преобразовать свои данные в объекты str.

for item in items:
    item = [x.encode('latin-1') for x in item]
    cleancsv.writerow(item)

Это было бы правильно, за исключением того, что у вас есть символ (U + 2022 BULLET) в ваших данных, а Latin-1 не может его представлять. Существует несколько способов решения этой проблемы:

  • Запишите x.encode('latin-1', 'ignore'), чтобы удалить пулю (или другие символы не латинского алфавита).
  • Напишите x.encode('latin-1', 'replace'), чтобы заменить маркер вопросительным знаком.
  • Замените пули символом Latin-1, например * или ·.
  • Используйте кодировку символов, которая содержит все необходимые символы.

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

Ответ 5

xlrd работает с Unicode, поэтому строка, которую вы возвращаете, является строкой Unicode. E-знак имеет кодовую точку U + 00A3, поэтому представление указанной строки должно быть u'\xa3'. Это было прочитано правильно; это строка, с которой вы должны работать в своей программе.

Когда вы пишете эту (абстрактную, Unicode) строку где-то, вам нужно выбрать кодировку. В этот момент вы должны .encode вставить это кодирование, скажем latin-1.


>>> book = xlrd.open_workbook( "test.xls" )
>>> sh = book.sheet_by_index( 0 )
>>> x = sh.cell_value( 0, 0 )
>>> x
u'\xa3'
>>> print x
£

# sample outputs (for e.g. writing to a file)
>>> x.encode( "latin-1" )
'\xa3'
>>> x.encode( "utf-8" )
'\xc2\xa3'

# garbage, because x is already Unicode
>>> x.decode( "ascii" )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa3' in position 0:
ordinal not in range(128)
>>>

Ответ 6

Работа с xlrd, у меня есть в строке... xl_data.find(str (cell_value))... которая дает ошибку: "кодек ascii не может кодировать символ u '\ xdf' в позиции 3: порядковый номер не в диапазоне (128)". Все предложения на форумах бесполезны для моих немецких слов. Но переход на:... xl_data.find(cell.value)... не дает ошибок. Итак, я полагаю, что использование строк в качестве аргументов в некоторых командах с xldr имеет специфические проблемы с кодировкой.