2010-10-14 24 views
5

Estoy usando una aplicación de Django para exportar una cadena a un archivo CSV. La cadena es un mensaje que se envió a través de un formulario de front-end. Sin embargo, he estado recibiendo este error cuando se proporciona una comilla simple Unicode en la entrada.Exportación de Python Unicode CSV (usando Django)

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

que he estado tratando de convertir el Unicode a ASCII utilizando el código de abajo, pero aún así obtener una error similar.

UnicodeEncodeError: 'ascii' codec can't encode characters in 
position 0-9: ordinal not in range(128) 

He tamizado a través de docenas de sitios web y he aprendido mucho acerca de Unicode, sin embargo, todavía no soy capaz de convertir este Unicode a ASCII. No me importa si el algoritmo elimina los caracteres Unicode. Las líneas comentadas indican varias opciones que he probado, pero el error persiste.

import csv 
import unicodedata 

... 

#message = unicode(unicodedata.normalize(
#       'NFKD',contact.message).encode('ascii','ignore')) 
#dmessage = (contact.message).encode('utf-8','ignore') 
#dmessage = contact.message.decode("utf-8") 
#dmessage = "%s" % dmessage 
dmessage = contact.message 

csv_writer.writerow([ 
     dmessage, 
]) 

¿Alguien tiene algún consejo para eliminar los caracteres Unicode para poder exportarlos a CSV? Este problema aparentemente fácil ha mantenido mi cabeza dando vueltas. Cualquier ayuda es muy apreciada. Gracias , Joe

+0

Gracias por la corrección de Glenn –

Respuesta

7

No puede codificar el carácter Unicode u'\u2019' (U + 2019 comilla de comillas derecha) en ASCII, porque ASCII no tiene ese carácter en él. ASCII es solo el alfabeto latino básico, los dígitos y la puntuación; no obtienes letras acentuadas o 'citas inteligentes' como este personaje.

Así que tendrá que elegir otra codificación. Ahora, normalmente, lo sensato sería exportar a UTF-8, que puede contener cualquier carácter Unicode. Desafortunadamente para usted si sus usuarios objetivo están usando Office (y probablemente lo sean), no podrán leer caracteres codificados en UTF-8 en CSV. En cambio, Excel leerá los archivos usando la página de códigos predeterminada del sistema para esa máquina (también conocida erróneamente como la página de códigos 'ANSI'), y terminará con mojibake como ’ en lugar de .

Eso significa que tiene que adivinar la página de códigos predeterminada del sistema del usuario si desea que los caracteres se muestren correctamente. Para los usuarios occidentales, esa será la página de códigos 1252. Los usuarios con instalaciones de Windows no occidentales verán los caracteres incorrectos, pero no hay nada que se pueda hacer al respecto (aparte de organizar una campaña de escritura de cartas a Microsoft para dejar caer la estúpida tontería con ANSI ya y usa UTF-8 como todos los demás).

La página de códigos 1252 puede contener U + 2019 (), pero obviamente hay muchos más caracteres que no puede representar. Para evitar obtener UnicodeEncodeError para esos caracteres, puede usar el argumento ignore (o replace para reemplazarlos con signos de interrogación).

dmessage= contact.message.encode('cp1252', 'ignore') 

alternativamente, para dar y quitar todas las caracteres no ASCII, para que todos tengan una igualmente mala experiencia, independientemente de la configuración regional:

dmessage= contact.message.encode('ascii', 'ignore') 
+1

@bobince: "adivina la página de códigos predeterminada del sistema del usuario" ... ¿qué problemas has experimentado tratando de obtener esto de forma autoritaria con 'locale.getpreferredencoding()' o 'locale.getdefaultlocale() [1]'? –

+2

@John: estoy pensando si Django está involucrado, estamos hablando de una aplicación del lado del servidor y no hay garantía de que la codificación predeterminada del servidor sea similar a la del cliente. (En el caso común de que el cliente sea Windows y el servidor no, las codificaciones nunca coincidirán). – bobince

+1

@bobince: la pregunta nunca se ha especificado; por todo lo que sabemos, el archivo csv podría ser solo para fines de persistencia y solo se usará internamente. –

2

La codificación es un dolor, pero si está trabajando en Django han intentado smart_unicode(str) de django.utils.encoding? Encuentro que eso suele ser el truco.

La única otra opción que he encontrado es utilizar el pitón incorporada encode() y decode() para cuerdas, pero hay que especificar la codificación para aquellos y honestamente, es un dolor.

+0

Gracias Waffel paradoja, voy a dar la smart_unicode un tiro y le permiten saber cómo va. –

1

[advertencia: No soy un djangoist ; django puede tener una mejor solución].

general no específicas de Django respuesta:

Si usted tiene un número más bien pequeño de caracteres no ASCII conocidos y hay equivalentes ASCII aceptable por el usuario para ellos, se puede configurar una tabla de traducción y el uso de la unicode.translate método:

smashcii = { 
    0x2019 : u"'", 
    # etc 
    # 

smashed = input_string.translate(smashcii) 
+0

Tendré que darle una oportunidad a este método. Podría superarme este problema al menos. Gracias por tu sugerencia. –

Cuestiones relacionadas