2010-10-14 11 views
5

Sto utilizzando un'app Django per esportare una stringa in un file CSV. La stringa è un messaggio inviato tramite un modulo di front-end. Tuttavia, ho ricevuto questo errore quando nell'input viene fornita una virgoletta unicode.Esportazione CSV Unicode Python (utilizzando Django)

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

Ho cercato di convertire l'unicode in ASCII usando il codice seguente, ma ancora ottenere un errore simile.

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

che ho passato al setaccio decine di siti web e imparato molto su unicode, tuttavia, non sono ancora in grado di convertire questo unicode in ASCII. Non mi interessa se l'algoritmo rimuove i caratteri Unicode. Le righe commentate indicano alcune varie opzioni che ho provato, ma l'errore 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, 
]) 

Qualcuno ha qualche consiglio su come rimuovere i caratteri Unicode posso esportarli in CSV? Questo problema apparentemente facile mi ha fatto girare la testa. Ogni aiuto è molto apprezzato. Grazie, Joe

+0

Grazie per la correzione Glenn –

risposta

7

Non è possibile codificare il carattere Unicode u'\u2019' (U + 2019 virgoletta singola destra) in ASCII, perché ASCII non ha quel carattere in esso. ASCII è solo l'alfabeto latino di base, le cifre e la punteggiatura; non hai lettere accentate o "citazioni intelligenti" come questo personaggio.

Quindi dovrai scegliere un'altra codifica. Ora normalmente la cosa più sensata da fare sarebbe esportare in UTF-8, che può contenere qualsiasi carattere Unicode. Sfortunatamente per te se i tuoi utenti target utilizzano Office (e probabilmente lo sono), non saranno in grado di leggere i caratteri codificati in UTF-8 in CSV. Invece Excel leggerà i file usando la tabella codici predefinita del sistema per quella macchina (anche in modo fuorviante nota come la code page 'ANSI'), e finirà con mojibake come ’ invece di .

Ciò significa che è necessario indovinare la tabella codici predefinita del sistema dell'utente se si desidera che i caratteri vengano visualizzati correttamente. Per gli utenti occidentali, questa sarà la code page 1252. Gli utenti con installazioni Windows non occidentali vedranno i caratteri sbagliati, ma non c'è nulla che tu possa fare al riguardo (oltre a organizzare una campagna di scrittura di lettere su Microsoft per abbandonare le stupide sciocchezze con ANSI già e usa UTF-8 come tutti gli altri).

Codice pagina 1252 può contenere U + 2019 (), ma ovviamente ci sono molti più caratteri che non può rappresentare. Per evitare di ottenere UnicodeEncodeError per questi caratteri, è possibile utilizzare l'argomento ignore (o replace per sostituirli con punti interrogativi).

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

in alternativa, a rinunciare e rimuovere tutti i caratteri non ASCII, in modo che ognuno abbia un altrettanto brutta esperienza a prescindere dalla localizzazione:

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

@bobince: "indovina la codepage predefinita del sistema dell'utente" ... Quali problemi hai riscontrato provando ad ottenerlo autorevolmente con 'locale.getpreferredencoding()' o 'locale.getdefaultlocale() [1]'? –

+2

@John: Penso che se Django è coinvolto stiamo parlando di un'app lato server e non c'è alcuna garanzia che la codifica predefinita del server sia qualcosa come quella del client. (Nel caso comune che il client sia Windows e il server non lo sia, le codifiche non corrisponderanno mai.) – bobince

+1

@bobince: la domanda non è mai stata specificata; per quanto ne sappiamo il file CSV potrebbe essere solo per scopi di persistenza e verrà utilizzato solo internamente. –

2

codifica è un dolore, ma se si sta lavorando in Django Hai provato smart_unicode(str) da django.utils.encoding? Trovo che di solito fa il trucco.

L'unica altra opzione che ho trovato è quello di utilizzare il pitone built-in encode() e decode() per le stringhe, ma è necessario specificare la codifica per chi e onestamente, è un dolore.

+0

Grazie Waffel Paradox, darò lo smart_unicode un colpo e ti faccio sapere come va. –

1

[avvertimento: io non sono un djangoist ; Django potrebbe avere una soluzione migliore].

Generale specifiche non django risposta:

Se si dispone di un numero piuttosto piccolo di caratteri non-ASCII noti e ci sono equivalenti ASCII dall'utente accettabili per loro, è possibile impostare una tabella di traduzione e utilizzare il unicode.translate metodo:

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

smashed = input_string.translate(smashcii) 
+0

Dovrò dare a questo metodo un colpo. Potresti almeno superare questo problema. Grazie per il tuo suggerimento. –