Codec UnicodeEncodeError:' ascii 'ne peut pas encoder le caractère u 'xa0 ' en position 20: ordinal pas dans la plage (128)
j'ai des problèmes avec les caractères unicode du texte récupéré à partir de différentes pages web (sur différents sites). Je suis à l'aide de BeautifulSoup.
Le problème est que l'erreur n'est pas toujours reproductible; il travaille parfois avec certaines pages, et parfois, il barfs en lançant un UnicodeEncodeError
. J'ai essayé à peu près tout ce à quoi je peux penser, et pourtant je n'ai rien trouvé qui fonctionne de manière cohérente sans jeter une sorte d'erreur liée à Unicode.
une des sections du code qui cause des problèmes est montrée ci-dessous:
agent_telno = agent.find('div', 'agent_contact_number')
agent_telno = '' if agent_telno is None else agent_telno.contents[0]
p.agent_info = str(agent_contact + ' ' + agent_telno).strip()
Voici une trace de pile produite sur certaines chaînes lorsque l'extrait ci-dessus est exécuté:
Traceback (most recent call last):
File "foobar.py", line 792, in <module>
p.agent_info = str(agent_contact + ' ' + agent_telno).strip()
UnicodeEncodeError: 'ascii' codec can't encode character u'xa0' in position 20: ordinal not in range(128)
je soupçonne que c'est parce que certaines pages (ou plus précisément, les pages de certains sites) peuvent être codés, tandis que d'autres peuvent être non codée. Tous les sites sont basés au Royaume-Uni et fournissent des données destinées à la consommation au Royaume - Uni. questions relatives à l'internalisation ou au traitement de textes rédigés dans une langue autre que l'anglais.
est-ce que quelqu'un a une idée sur la façon de résoudre ce problème pour que je puisse toujours le résoudre?
19 réponses
vous devez lire le python Unicode HOWTO . Cette erreur est le tout premier exemple .
en gros, arrêtez d'utiliser str
pour convertir unicode en texte encodé / octets.
à la place, utilisez correctement .encode()
pour coder la chaîne:
p.agent_info = u' '.join((agent_contact, agent_telno)).encode('utf-8').strip()
ou travailler entièrement en unicode.
c'est un point de douleur Python unicode classique! Considérons ce qui suit:
a = u'bats\u00E0'
print a
=> batsà
tout bon jusqu'à présent, mais si nous appelons str(a), voyons ce qui se passe:
str(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)
oh dip, ça ne fera de bien à personne! Pour corriger l'erreur, de coder les octets explicitement .encoder et dire à python quel codec utiliser:
a.encode('utf-8')
=> 'bats\xc3\xa0'
print a.encode('utf-8')
=> batsà
voilà!
Le problème est que lorsque vous appelez str(), python utilise le codage de caractères par défaut pour essayer de coder les octets que vous lui avez donnés, qui dans votre cas sont parfois des représentations de caractères unicode. Pour résoudre le problème, vous devez dire à python comment gérer la chaîne que vous lui donnez en utilisant .encoder ("whatever_unicode"). La plupart du temps, vous devriez être bien en utf-8.
pour une excellente exposition sur ce sujet, voir Ned Batchelder PyCon talk ici: http://nedbatchelder.com/text/unipain.html
j'ai trouvé un travail élégant pour moi d'enlever les symboles et de continuer à garder la corde comme la corde dans ce qui suit:
yourstring = yourstring.encode('ascii', 'ignore').decode('ascii')
il est important de noter que l'utilisation de l'option ignore est dangereux parce qu'il supprime silencieusement tout support unicode (et internationalisation) du code qui l'utilise, comme vu ici (convertissez unicode):
>>> u'City: Malmö'.encode('ascii', 'ignore').decode('ascii')
'City: Malm'
Eh bien j'ai tout essayé, mais cela n'a pas aidé, après avoir cherché sur Google autour de moi j'ai pensé que ce qui suit et il a aidé. python 2.7 est en cours d'utilisation.
# encoding=utf8
import sys
reload(sys)
sys.setdefaultencoding('utf8')
un problème subtil qui provoque même l'échec de l'impression est que les variables d'environnement sont mal définies, par exemple: ici LC_ALL défini à "C". Dans Debian, ils déconseillent de le configurer: wiki Debian sur Locale
$ echo $LANG
en_US.utf8
$ echo $LC_ALL
C
$ python -c "print (u'voil\u00e0')"
Traceback (most recent call last):
File "<string>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)
$ export LC_ALL='en_US.utf8'
$ python -c "print (u'voil\u00e0')"
voilà
$ unset LC_ALL
$ python -c "print (u'voil\u00e0')"
voilà
j'ai en fait trouvé que dans la plupart de mes cas, simplement enlever ces caractères est beaucoup plus simple:
s = mystring.decode('ascii', 'ignore')
pour moi, ce qui a fonctionné était:
BeautifulSoup(html_text,from_encoding="utf-8")
J'espère que ça aidera quelqu'un.
ajouter la ligne ci-dessous au début de votre script ( ou comme deuxième ligne):
# -*- coding: utf-8 -*-
C'est la définition de l'encodage du code source python. Plus d'informations dans PEP 263 .
le problème est que vous essayez d'imprimer un caractère unicode, mais votre terminal ne le supporte pas.
vous pouvez essayer d'installer language-pack-en
paquet pour corriger cela:
sudo apt-get install language-pack-en
qui fournit des mises à jour des données de traduction en anglais pour tous les paquets pris en charge (y compris Python). Installez un paquet de langue différent si nécessaire (en fonction des caractères que vous essayez d'imprimer).
sur certains Linux distributions il est nécessaire afin de s'assurer que les locales par défaut en anglais sont configurées correctement (donc les caractères unicode peuvent être manipulés par shell/terminal). Il est parfois plus facile de l'installer, de configurer manuellement.
, Puis lors de l'écriture du code, assurez-vous d'utiliser le bon encodage dans votre code.
par exemple:
open(foo, encoding='utf-8')
si vous avez encore un problème, vérifiez deux fois la configuration de votre système, par exemple::
-
votre fichier local (
/etc/default/locale
), qui devrait avoir par exempleLANG="en_US.UTF-8" LC_ALL="en_US.UTF-8"
-
valeur de
LANG
/LC_CTYPE
dans la coquille. -
Vérifiez quel emplacement votre shell supporte par:
locale -a | grep "UTF-8"
démontrer le problème et la solution fraîches de la VM.
-
Initialiser et fournir la VM (p.ex. en utilisant
vagrant
):vagrant init ubuntu/trusty64; vagrant up; vagrant ssh
Voir: disponible Ubuntu boîtes . .
-
impression de caractères unicodes (tels que le signe de marque comme
™
):$ python -c 'print(u"\u2122");' Traceback (most recent call last): File "<string>", line 1, in <module> UnicodeEncodeError: 'ascii' codec can't encode character u'\u2122' in position 0: ordinal not in range(128)
-
Maintenant installation de
language-pack-en
:$ sudo apt-get -y install language-pack-en The following extra packages will be installed: language-pack-en-base Generating locales... en_GB.UTF-8... /usr/sbin/locale-gen: done Generation complete.
-
maintenant le problème est résolu:
$ python -c 'print(u"\u2122");' ™
voici un rappel d'autres réponses soi-disant" balancer". Il y a des situations dans lesquelles le simple fait de jeter les caractères/cordes gênants est une bonne solution, malgré les protestations exprimées ici.
def safeStr(obj):
try: return str(obj)
except UnicodeEncodeError:
return obj.encode('ascii', 'ignore').decode('ascii')
except: return ""
Test:
if __name__ == '__main__':
print safeStr( 1 )
print safeStr( "test" )
print u'98\xb0'
print safeStr( u'98\xb0' )
Résultats:
1
test
98°
98
Suggestion: vous pourriez appeler cette fonction toAscii
à la place? C'est une question de préférence.
Essayer cela pourrait résoudre,
# encoding=utf8
import sys
reload(sys)
sys.setdefaultencoding('utf8')
de Simples fonctions d'assistance trouvé ici .
def safe_unicode(obj, *args):
""" return the unicode representation of obj """
try:
return unicode(obj, *args)
except UnicodeDecodeError:
# obj is byte string
ascii_text = str(obj).encode('string_escape')
return unicode(ascii_text)
def safe_str(obj):
""" return the byte string representation of obj """
try:
return str(obj)
except UnicodeEncodeError:
# obj is unicode
return unicode(obj).encode('unicode_escape')
je viens d'utiliser ce qui suit:
import unicodedata
message = unicodedata.normalize("NFKD", message)
vérifiez ce que la documentation en dit:
unicodedata.normaliser (form, unistr) retourner la forme normale pour la chaîne Unicode unistr. Les valeurs valides pour la forme sont ‘NFC', ' NFKC’, "NFD" et "NFKD".
la norme Unicode définit diverses formes de normalisation D'une Unicode chaîne, basée sur la définition de l'équivalence canonique et équivalence de compatibilité. En Unicode, plusieurs caractères peuvent être exprimé de différentes manières. Par exemple, le caractère U+00C7 (LATIN La lettre C majuscule avec CEDILLA) peut également être exprimée comme la séquence U+0043 (LETTRE C DE LA CAPITALE LATINE) U+0327 (COMBINAISON CEDILLA).
pour chaque caractère, il y a deux formes normales: la forme C normale et la forme C normale. forme normale D. La Forme Normale D (NFD) est aussi connue sous le nom de forme canonique décomposition, et traduit chaque caractère en son décomposé forme. La forme normale C (NFC) applique d'abord une décomposition canonique, puis compose à nouveau des caractères pré-combinés.
En plus de ces deux formes, il existe deux autres formes normales basé sur l'équivalence de compatibilité. En Unicode, certains caractères sont pris en charge qui normalement serait unifié avec d'autres caractères. Pour exemple, U+2160 (chiffre romain un) est en fait la même chose que U+0049 (LETTRE LATINE MAJUSCULE I). Cependant, il est pris en charge en Unicode pour compatibilité avec les jeux de caractères existants (par exemple gb2312).
la forme normale KD (NFKD) appliquera la décomposition de compatibilité, c'est-à-dire remplacer tous les caractères de compatibilité par leurs équivalents. Le la forme normale KC (NFKC) applique d'abord la décomposition de compatibilité, suivi de la composition canonique.
même si deux chaînes unicode sont normalisées et ressemblent à la même chose lecteur humain, si l'on a combinant des caractères et l'autre n'a pas, ils peuvent ne pas comparer égal.
résout ça pour moi. Simple et facile.
j'ai toujours mis le code ci-dessous dans les deux premières lignes des fichiers python:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
il suffit d'ajouter à un encodage variable('utf-8')
agent_contact.encode('utf-8')
nous avons frappé cette erreur en lançant manage.py migrate
dans Django avec des fixtures localisées.
notre source contenait la déclaration # -*- coding: utf-8 -*-
, MySQL était correctement configuré pour utf8 et Ubuntu avait le pack de langue et les valeurs appropriées dans /etc/default/locale
.
le problème était simplement que le conteneur Django (nous utilisons docker) manquait le LANG
env var.
paramètre LANG
à en_US.UTF-8
et redémarrer le conteneur avant de relancer migrations a résolu le problème.
ci-dessous la solution a fonctionné pour moi, vient d'ajouter
u "Chaîne"
(représentant la chaîne en unicode) devant ma chaîne.
result_html = result.to_html(col_space=1, index=False, justify={'right'})
text = u"""
<html>
<body>
<p>
Hello all, <br>
<br>
Here's weekly summary report. Let me know if you have any questions. <br>
<br>
Data Summary <br>
<br>
<br>
{0}
</p>
<p>Thanks,</p>
<p>Data Team</p>
</body></html>
""".format(result_html)
je viens d'avoir ce problème, et Google m'a conduit ici, donc juste pour ajouter aux solutions générales ici, c'est ce qui a fonctionné pour moi:
# 'value' contains the problematic data
unic = u''
unic += value
value = unic
j'ai eu cette idée Après avoir lu présentation de Ned .
je ne prétends pas comprendre pleinement pourquoi cela fonctionne bien. Donc, si quelqu'un peut modifier cette réponse ou mettre un commentaire pour expliquer, je l'apprécierai.
si vous avez quelque chose comme packet_data = "This is data"
alors faites ceci sur la ligne suivante, juste après avoir initialisé packet_data
:
unic = u''
packet_data = unic