3 votes

Convertir Unicode en python

Duplicata possible :
Convertir Unicode en UTF-8 Python

Je suis un tout nouveau programmeur python, travaillant sur mon premier script. Le script tire un texte d'une chaîne plist, puis lui fait quelques choses, puis l'emballe comme un email HTML.

à partir de quelques entrées, j'obtiens la redoutable erreur Unicode "outside ordinal 128".

Après avoir lu tout ce que j'ai pu trouver sur l'encodage et le décodage, je sais qu'il est important pour moi d'obtenir l'encodage, mais j'ai du mal à comprendre quand et comment le faire exactement.

La variable incriminée est d'abord extraite à l'aide de plistlib, puis convertie en HTML à partir de markdown, comme ceci :

entry = result['Entry Text']
donotecontent = markdown2.markdown(entry)

Plus tard, il est mis dans l'email comme ceci :

html = donotecontent + '<br /><br />' + var3
part1 = MIMEText(html, 'html')
msg.attach(part1)

Ma question est la suivante : quel est le meilleur moyen de m'assurer que les caractères Unicode présents dans ce contenu ne provoquent pas d'erreur. Je préfère ne pas ignorer les caractères.

11voto

Désolé pour mon mauvais anglais. Je parle chinois/japonais, et j'utilise les caractères CJK tous les jours. Ceron a résolu la quasi-totalité de ce problème, je ne parlerai donc pas de la façon d'utiliser les caractères CJK. encode() / decode() encore.

Lorsque nous utilisons str() pour convertir n'importe quel objet unicode, il encodera la chaîne unicode en bytedata ; lorsque nous utilisons unicode() pour lancer str il décodera les bytedata en caractères unicode.

Et, l'encodage doit être celui renvoyé par la fonction sys.getdefaultencoding() .

Par défaut, sys.getdefaultencoding() renvoie 'ascii' par défaut, l'exception d'encodage/décodage peut être levée lors de l'exécution de l'opération. str() / unicode() le casting.

Si vous voulez faire la conversion str <-> unicode en str() o unicode() et aussi, l'encodage/décodage implicite avec 'utf-8', vous pouvez exécuter l'instruction suivante :

import sys    # sys.setdefaultencoding is cancelled by site.py
reload(sys)    # to re-enable sys.setdefaultencoding()
sys.setdefaultencoding('utf-8')

et cela entraînera l'exécution ultérieure de str() y unicode() convertit tout objet basestring avec un encodage utf-8.

Cependant, je préférerais utiliser encode() / decode() explicitement, parce que cela rend la maintenance du code plus facile pour moi.

4voto

Manuel Ceron Points 3568

Si vous utilisez Python 2.x, n'oubliez pas qu'il existe deux types de chaînes de caractères : str y unicode . str sont des chaînes d'octets, tandis que unicode sont des chaînes de caractères unicode. unicode Les chaînes de caractères peuvent être utilisées pour représenter du texte dans n'importe quelle langue, mais pour stocker du texte dans un ordinateur ou l'envoyer par courrier électronique, vous devez représenter ce texte à l'aide d'octets. Pour représenter du texte à l'aide d'octets, vous avez besoin d'un format de codage. Il existe de nombreux formats de codage, Python utilise ascii par défaut, mais ascii ne peut représenter que quelques caractères, principalement des lettres anglaises. Si vous essayez de coder un texte avec d'autres lettres à l'aide de la fonction ascii vous obtiendrez le fameux "outside ordinal 128". Par exemple :

>>> u'Cerón'.encode('ascii')
Traceback (most recent call last):
  File "<input>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf3' in position 3:
 ordinal not in range(128)

La même chose se produit si vous utilisez str(u'Cerón') car Python utilise ascii par défaut pour convertir unicode a str .

Pour que cela fonctionne, vous devez utiliser un format de codage différent. UTF-8 est un format de codage qui permet d'exprimer tout texte unicode sous forme d'octets. Pour convertir le u'Cerón' chaîne unicode en octets que vous devez utiliser :

>>> u'Cerón'.encode('utf-8')
'Cer\xc3\xb3n'

Aucune erreur cette fois-ci.

Maintenant, revenons à votre problème d'email. Je peux voir que vous utilisez MIMEText qui accepte un code déjà encodé str dans votre cas, c'est l'argument html variable. MIMEText accepte également un argument spécifiant le type d'encodage utilisé. Ainsi, dans votre cas, si html est une chaîne unicode, vous devez la coder en tant que utf-8 et passer le paramètre charset aussi (parce que HTMLText utilise ascii par défaut) :

part1 = MIMEText(html.encode('utf-8'), 'html', 'utf-8')

Mais faites attention, car si html est déjà un str au lieu de unicode alors l'encodage échouera. C'est l'un des problèmes de Python 2.x, il vous permet d'encoder une chaîne déjà encodée mais il jette une erreur.

Un autre problème à ajouter à la liste est que utf-8 est compatible avec ascii et Python essaiera toujours d'encoder/décoder automatiquement les chaînes de caractères à l'aide de ascii . Si vous n'encodez pas correctement vos chaînes de caractères, mais que vous utilisez seulement ascii personnages, les choses fonctionneront bien. Toutefois, si pour une raison quelconque, certains non-ascii caractères se glisse dans votre message, vous obtiendrez l'erreur, ce qui rend les erreurs plus difficiles à détecter.

0voto

pylover Points 2553

Rappelez-vous : vous ne pouvez pas décoder un unicode, et vous ne pouvez pas encoder une chaîne de caractères.

>>> u"\xa0".decode("ascii", "ignore")

Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    u"\xa0".decode("ascii", "ignore")
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 0: ordinal not in range(128)

>>> "\xc2".encode("ascii", "ignore")

Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    "\xc2".encode("ascii", "ignore")
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 0: ordinal not in range(128)

Découvrez cet excellent tutoriel

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X