UnicodeEncodeError: el codec ‘ascii’ no puede codificar el carácter u ‘\ xa3’

Tengo una hoja de cálculo de Excel que estoy leyendo que contiene algunos signos de £.

Cuando bash leerlo utilizando el módulo xlrd, aparece 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 generar un error, pero desafortunadamente cuando escribo los datos en otro lugar (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 descifrarlo 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  cleancsv.writerow(item) UnicodeEncodeError: 'ascii' codec can't encode character u'\u2022' in position 43: ordinal not in range(128) 

    Recibo el mismo error incluso si descomento la línea Latin-1.

    El fragmento de código dice x.decode , pero está recibiendo un error de encoding , 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 Para propósitos de E / S (para su propio uso interno del progtwig, 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).

    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) 

    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?

    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). Los mensajes de error de lectura ayudan cuidadosamente 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 habría ayudado a obtener una mejor respuesta antes si hubiera mencionado por adelantado que estaba trabajando en Mac OS X … el sospechoso habitual de una encoding adecuada para CSV es cp1252 (Windows), no mac-roman .

     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 deencoding .

    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 encoding 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 encoding 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 encoding para archivos de texto.

    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 progtwig.

    Cuando escribe esta cadena (abstracta, Unicode) en algún lugar, debe elegir una encoding. En ese momento, debe .encode en esa encoding, 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 eg 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 "", line 1, in  UnicodeEncodeError: 'ascii' codec can't encode character u'\xa3' in position 0: ordinal not in range(128) >>> 

    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 alemanas. 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 encoding específicos.