2010-10-14 7 views
5

J'utilise une application Django pour exporter une chaîne dans un fichier CSV. La chaîne est un message qui a été envoyé via un formulaire frontal. Cependant, j'ai reçu cette erreur quand un guillemet simple unicode est fourni dans l'entrée.Export CSV Python Unicode (avec Django)

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

J'ai essayé de convertir le unicode en ascii utilisant le code ci-dessous, mais toujours obtenir une erreur semblable.

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

J'ai passé au crible à travers des dizaines de sites Web et beaucoup appris sur unicode, cependant, je ne suis toujours pas en mesure de convertir cette ascii unicode. Je me fiche que l'algorithme supprime les caractères Unicode. Les lignes commentées indiquent quelques options que j'ai essayées, mais l'erreur 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, 
]) 

Quelqu'un a-t-il des conseils pour supprimer les caractères Unicode afin que je puisse les exporter au format CSV? Ce problème apparemment facile m'a fait tourner la tête. Toute aide est très appréciée. Merci, Joe

+0

Merci pour le correctif Glenn –

Répondre

7

Vous ne pouvez pas encoder le caractère Unicode u'\u2019' (U + 2019 Cotation simple droite) en ASCII, car ASCII ne possède pas ce caractère. ASCII est seulement l'alphabet latin de base, les chiffres et la ponctuation; vous n'obtenez pas de lettres accentuées ou de «citations intelligentes» comme ce personnage.

Vous devrez donc choisir un autre encodage. Maintenant normalement la chose sensée à faire serait d'exporter vers UTF-8, qui peut contenir n'importe quel caractère Unicode. Malheureusement pour vous si vos utilisateurs cibles utilisent Office (et ils le sont probablement), ils ne pourront pas lire les caractères codés en UTF-8 au format CSV. Au lieu de cela Excel lira les fichiers en utilisant la page de code par défaut du système pour cette machine (également trompeusement connu comme la page de code 'ANSI'), et se retrouvera avec mojibake comme ’ au lieu de . Cela signifie que vous devez deviner la page de code par défaut du système de l'utilisateur si vous voulez que les caractères s'affichent correctement. Pour les utilisateurs occidentaux, il s'agira de la page de codes 1252. Les utilisateurs disposant d'installations Windows non occidentales verront les caractères erronés, mais vous ne pouvez rien y faire (autre que d'organiser une campagne de rédaction de lettres à Microsoft pour abandonner le stupide non-sens. ANSI déjà et utiliser UTF-8 comme tout le monde). La page de code 1252 peut contenir U + 2019 (), mais il y a évidemment beaucoup plus de caractères qu'elle ne peut pas représenter. Pour éviter d'obtenir UnicodeEncodeError pour ces caractères, vous pouvez utiliser l'argument ignore (ou replace pour les remplacer par des points d'interrogation).

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

alternativement, d'abandonner et de supprimer tous les caractères non-ASCII, afin que chacun ait une expérience tout aussi mal quel que soit locale:

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

@bobince: "devinez la page de codes système par défaut de l'utilisateur" ... quels problèmes avez-vous rencontrés en essayant de l'obtenir avec autorité: 'locale.getpreferredencoding()' ou 'locale.getdefaultlocale() [1]'? –

+2

@John: Je pense que si Django est impliqué nous parlons d'une application côté serveur et il n'y a aucune garantie que l'encodage par défaut du serveur est quelque chose comme celui du client. (Dans le cas courant que le client est Windows et le serveur ne l'est pas, les encodages ne correspondront jamais.) – bobince

+1

@bobince: La question n'a jamais été spécifiée; pour tout ce que nous savons le fichier csv pourrait juste être à des fins de persistance et ne sera utilisé en interne. –

2

Le codage est une douleur, mais si vous travaillez dans django vous avez essayé de smart_unicode(str)django.utils.encoding? Je trouve que cela fait habituellement l'affaire.

La seule autre option que j'ai trouvé est d'utiliser le python intégré encode() et decode() pour les chaînes, mais vous devez spécifier l'encodage pour ceux-ci et honnêtement, c'est une douleur.

+0

Merci Waffel Paradox, je vais donner la smart_unicode un coup et vous laisser savoir comment ça se passe. –

1

[mise en garde: Je ne suis pas djangoist ; django peut avoir une meilleure solution].

réponse générale non spécifique à django:

Si vous avez un nombre assez petit de caractères non-ASCII connus et il y a des équivalents ASCII acceptables utilisateur pour eux, vous pouvez mettre en place une table de traduction et utiliser le unicode.translate méthode:

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

smashed = input_string.translate(smashcii) 
+0

Je vais devoir essayer cette méthode. Pourrais-je me débarrasser de ce problème au moins. Merci pour votre suggestion. –