python - xf1 - UnicodeEncodeError: el codec ''ascii'' no puede codificar el carácter u ''/ xa3''
unicodeencodeerror: ''ascii'' codec can''t encode character (6)
El fragmento de código dice x.decode
, pero está recibiendo un error de codificación , lo que significa que x
ya es Unicode, por lo tanto, para "descodificarlo", primero debe convertirse en una cadena de bytes (y ahí es donde se encuentra el códec predeterminado). aparece y falla). En tu texto entonces dices "si reescribo ot to x. Encode " ... lo que parece implicar que sabes que x es Unicode.
Entonces, ¿qué es lo que estás haciendo, y qué es lo que quieres hacer, codificar un x
unicode para obtener una cadena de bytes codificada, o descodificar una cadena de bytes en un objeto unicode?
Me parece desafortunado que pueda llamar a encode
en una cadena de bytes y a decode
en un objeto Unicode, porque creo que parece llevar a los usuarios a nada más que confusión ... pero al menos en este caso parece que logra propagar la confusión. (Al menos para mí ;-).
Si, como parece, x
es unicode, entonces nunca querrá "descodificarlo", es posible que desee codificarlo para obtener una cadena de bytes con un determinado códec, por ejemplo, latin-1, si eso es lo que necesita para algún tipo de propósitos de E / S (para su propio uso interno del programa, recomiendo seguir usando Unicode todo el tiempo, solo codifique / decodifique si y cuando absolutamente necesita , o recibe , cadenas de bytes codificadas para propósitos de entrada / salida).
Tengo una hoja de cálculo de Excel que estoy leyendo que contiene algunos signos de £.
Cuando intento leerlo usando el módulo xlrd, obtengo el siguiente error:
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)
Si reescribo esto en x.encode (''utf-8''), deja de emitir un error, pero desafortunadamente cuando escribo los datos en otra parte (como latin-1), los signos £ se han vuelto ilegibles.
¿Cómo puedo solucionar esto y leer los signos de inicio de sesión correctamente?
--- ACTUALIZACIÓN ---
Algunos lectores amables han sugerido que no necesito descodificarlo en absoluto, o que simplemente puedo codificarlo en Latin-1 cuando lo necesite. El problema con esto es que necesito escribir los datos en un archivo CSV eventualmente, y parece que se opone a las cadenas en bruto.
Si no codifico o decodifico los datos, entonces esto sucede (después de haber agregado la cadena a una matriz llamada elementos):
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)
Recibo el mismo error aunque descomente la línea Latin-1.
Por lo que vale la pena: soy el autor de xlrd
.
¿ xlrd
produce unicode?
Opción 1: lea la sección Unicode en la parte inferior de la primera pantalla de xlrd
doc: Este módulo presenta todas las cadenas de texto como objetos de Python Unicode.
Opción 2: print type(text), repr(text)
Dice "" "Si reescribo esto en x.encode (''utf-8''), deja de emitir un error, pero desafortunadamente cuando escribo los datos en otro lugar (como latin-1), todos los signos se han convertido en "" "Claro que si escribes texto codificado en UTF-8 en un dispositivo que está esperando latin1, será confuso. ¿Qué esperabas?
Usted dice en su edición: "" "Recibo el mismo error incluso si descomento la línea Latin-1" "". Esto es muy improbable; mucho más probable es que haya un error ligeramente diferente (mencionando el códec latin1 en lugar del códec ascii) en una línea de origen diferente (la línea latin1 sin comentarios en lugar de la línea de escritura). Leer los mensajes de error cuidadosamente ayuda a la comprensión.
Su problema aquí es que, en general, sus datos NO son codificables en latin1; muy pocos datos del mundo real es. Su SEÑAL DE VOZ se puede codificar en latin1, pero no son todos sus datos que no son ASCII. El carácter problemático es U + 2022 BULLET que no es codificable en latin1.
Le hubiera ayudado a obtener una mejor respuesta antes si hubiera mencionado por adelantado que estaba trabajando en Mac OS X ... el sospechoso habitual de una codificación adecuada para CSV es cp1252
(Windows), no mac-roman
.
Trabajando con xlrd, tengo en una línea ... xl_data.find (str (valor_célula)) ... que da el error: "el códec '''' ascii ''no puede codificar el carácter u'' / xdf ''en la posición 3: ordinal no en rango (128) ". Todas las sugerencias en los foros han sido inútiles para mis palabras en alemán. Pero cambiando a: ... xl_data.find (cell.value) ... no da error. Entonces, supongo que el uso de cadenas como argumentos en ciertos comandos con xldr tiene problemas de codificación específicos.
Una forma muy fácil de evitar todos los problemas del códec "''ascii'' no puede codificar caracteres ..." con csvwriter es usar unicodecsv , un reemplazo para csvwriter.
Instale unicodecsv con pip y luego puede usarlo de la misma manera, por ejemplo:
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)
xlrd
funciona con Unicode, por lo que la cadena que recibe es una cadena Unicode. El signo £ tiene el punto de código U + 00A3, por lo que la representación de dicha cadena debe ser u''/xa3''
. Esto se ha leído correctamente; es la cadena con la que deberías trabajar a lo largo de tu programa.
Cuando escribe esta cadena (abstracta, Unicode) en algún lugar, debe elegir una codificación. En ese momento, debe .encode
en esa codificación, digamos 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)
>>>
x = x.decode("ISO-8859-1")
UnicodeEncodeError: ''ascii'' codec can''t encode character u''/xa3'' in position 0: ordinal not in range(128)
Mire detenidamente: Obtuvo un error Unicode *** Encode *** al llamar al método de decodificación .
La razón de esto es que la decode
está destinada a convertirse de una secuencia de bytes ( str
) a un objeto unicode
. Pero, como dijo John, xlrd
ya usa cadenas Unicode, por lo que x
ya es un objeto unicode
.
En esta situación, Python 2.x asume que pretendías decodificar un objeto str
, por lo que "útilmente" crea uno para ti. Pero para convertir un unicode
en un str
, necesita una codificación y elige ASCII porque es el denominador común más bajo de las codificaciones de caracteres. Su código efectivamente se interpreta como
x = x.encode(''ascii'').decode("ISO-8859-1")
que falla porque x
contiene un carácter no ASCII.
Dado que x
ya es un objeto unicode
, la decode
es necesaria. Sin embargo, ahora se encuentra con el problema de que el módulo csv
Python 2.x no es compatible con Unicode. Tienes que convertir tus datos a objetos str
.
for item in items:
item = [x.encode(''latin-1'') for x in item]
cleancsv.writerow(item)
Esto sería correcto, excepto que tiene el carácter •
(BULLET U + 2022) en sus datos y Latin-1 no puede representarlo. Hay varias formas de solucionar este problema:
- Escriba
x.encode(''latin-1'', ''ignore'')
para eliminar la viñeta (u otros caracteres que no sean Latin-1). - Escriba
x.encode(''latin-1'', ''replace'')
para reemplazar la bala con un signo de interrogación. - Reemplace las balas con un carácter Latin-1 como
*
o·
. - Use una codificación de caracteres que contenga todos los caracteres que necesita.
En estos días, se admite ampliamente UTF-8, por lo que hay pocas razones para usar cualquier otra codificación para archivos de texto.