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?

989
demandé sur ShaneB 2012-03-30 16:06:41

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.

1095
répondu agf 2017-10-04 22:59:40

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

379
répondu Andbdrew 2012-08-02 14:16:05

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'
174
répondu Max Korolevsky 2018-05-19 14:42:35

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')
116
répondu Ashwin 2016-09-02 13:10:37

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à
75
répondu maxpolk 2013-12-02 18:04:24

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')
25
répondu Phil LaNasa 2013-11-01 13:44:36

pour moi, ce qui a fonctionné était:

BeautifulSoup(html_text,from_encoding="utf-8")

J'espère que ça aidera quelqu'un.

24
répondu Animesh 2015-01-26 14:53:34

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 .

17
répondu Andriy Ivaneyko 2016-08-08 10:17:31

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 exemple

    LANG="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.

  1. Initialiser et fournir la VM (p.ex. en utilisant vagrant ):

    vagrant init ubuntu/trusty64; vagrant up; vagrant ssh
    

    Voir: disponible Ubuntu boîtes . .

  2. 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)
    
  3. 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.
    
  4. maintenant le problème est résolu:

    $ python -c 'print(u"\u2122");'
    ™
    
14
répondu kenorb 2017-09-26 12:07:32

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.

10
répondu BuvinJ 2018-04-05 13:58:14

Essayer cela pourrait résoudre,

# encoding=utf8
import sys
reload(sys)
sys.setdefaultencoding('utf8')
8
répondu Joseph Daudi 2018-06-23 17:54:43

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')
6
répondu Parag Tyagi -morpheus- 2015-12-31 11:18:22

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.

3
répondu Drag0 2016-11-27 21:59:51

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
3
répondu Pereira 2018-02-27 14:40:22

il suffit d'ajouter à un encodage variable('utf-8')

agent_contact.encode('utf-8')
2
répondu Kairat Koibagarov 2018-01-31 05:50:36

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.

2
répondu followben 2018-04-11 07:26:07

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)
2
répondu Aravind Krishnakumar 2018-05-30 22:57:25

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.

1
répondu pepoluan 2016-03-12 03:14:47

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
0
répondu Nandan Kulkarni 2018-04-03 09:46:31