web-dev-qa-db-fra.com

"UnicodeEncodeError: le codec 'ascii' ne peut pas coder le caractère"

J'essaie de passer de grandes chaînes de code HTML aléatoire via des expressions régulières et mon script Python 2.6 s'étouffe à ce sujet:

UnicodeEncodeError: le codec 'ascii' ne peut pas coder le caractère

Je l'ai retracée à un exposant de marque à la fin de ce mot: Protection ™ - et je m'attends à en rencontrer d'autres à l'avenir.

Existe-t-il un module pour traiter les caractères non ascii? ou, quelle est la meilleure façon de gérer/échapper les choses non-ascii en python?

Merci! Erreur complète:

E
======================================================================
ERROR: test_untitled (__main__.Untitled)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Python26\Test2.py", line 26, in test_untitled
    ofile.write(Whois + '\n')
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2122' in position 1005: ordinal not in range(128)

Script complet:

from Selenium import Selenium
import unittest, time, re, csv, logging

class Untitled(unittest.TestCase):
    def setUp(self):
        self.verificationErrors = []
        self.Selenium = Selenium("localhost", 4444, "*firefox", "http://www.BaseDomain.com/")
        self.Selenium.start()
        self.Selenium.set_timeout("90000")

    def test_untitled(self):
        sel = self.Selenium
        spamReader = csv.reader(open('SubDomainList.csv', 'rb'))
        for row in spamReader:
            sel.open(row[0])
            time.sleep(10)
            Test = sel.get_text("//html/body/div/table/tbody/tr/td/form/div/table/tbody/tr[7]/td")
            Test = Test.replace(",","")
            Test = Test.replace("\n", "")
            ofile = open('TestOut.csv', 'ab')
            ofile.write(Test + '\n')
            ofile.close()

    def tearDown(self):
        self.Selenium.stop()
        self.assertEqual([], self.verificationErrors)

if __name__ == "__main__":
    unittest.main()
27
KenBurnsFan1

Vous essayez de passer un bytestring à quelque chose, mais il est impossible (à cause de la rareté des informations que vous fournissez) de dire quoi vous essayez de le transmettre. Vous commencez avec une chaîne Unicode qui ne peut pas être codée en tant que ASCII (le codec par défaut), donc, vous devrez coder par un codec différent (ou le transliter, comme @ R.Pate le suggère ) - mais il est impossible d'utiliser pour dire quel codec vous devez utiliser, car nous ne savons pas ce que vous passez le bytestring et donc don Je ne sais pas ce que ce sous-système inconnu va être en mesure d'accepter et de traiter correctement en termes de codecs.

Dans une obscurité totale où vous nous laissez, utf-8 Est une supposition aveugle raisonnable (car c'est un codec qui peut représenter n'importe quelle chaîne Unicode exactement comme un bytestring, et c'est le codec standard à de nombreuses fins, comme XML) - mais cela ne peut être qu'une supposition aveugle, jusqu'à ce que et à moins que vous ne nous en disiez plus sur quoi vous essayez de passer ce bytestring à, et à quelles fins.

Passer thestring.encode('utf-8') plutôt que nue thestring évitera certainement l'erreur particulière que vous voyez en ce moment, mais cela peut entraîner des affichages particuliers (ou quoi que ce soit is you essayons de faire avec ce bytestring!) à moins que le destinataire ne soit prêt, disposé et capable d'accepter le codage utf-8 (et comment pourrait WE savoir, avoir absolument aucune idée de ce que le destinataire pourrait peut-être?! -)

21
Alex Martelli

Vous essayez de convertir unicode en ascii en mode "strict":

>>> help(str.encode)
Help on method_descriptor:

encode(...)
    S.encode([encoding[,errors]]) -> object

    Encodes S using the codec registered for encoding. encoding defaults
    to the default encoding. errors may be given to set a different error
    handling scheme. Default is 'strict' meaning that encoding errors raise
    a UnicodeEncodeError. Other possible values are 'ignore', 'replace' and
    'xmlcharrefreplace' as well as any other name registered with
    codecs.register_error that is able to handle UnicodeEncodeErrors.

Vous voulez probablement quelque chose comme l'un des suivants:

s = u'Protection™'

print s.encode('ascii', 'ignore')    # removes the ™
print s.encode('ascii', 'replace')   # replaces with ?
print s.encode('ascii','xmlcharrefreplace') # turn into xml entities
print s.encode('ascii', 'strict')    # throw UnicodeEncodeErrors
32
Seth

La "meilleure" façon dépend toujours de vos besoins; alors, quelles sont les vôtres? L'ignorance non ASCII est-elle appropriée? Devriez-vous remplacer ™ par "(tm)"? (Ce qui semble sophistiqué pour cet exemple, mais se décompose rapidement pour d'autres points de code, mais cela peut être exactement ce que vous voulez.) L'exception pourrait-elle être exactement ce dont vous avez besoin; maintenant vous avez juste besoin de le gérer d'une manière ou d'une autre?

Vous seul pouvez vraiment répondre à cette question.

1
Roger Pate

Tout d'abord, essayez d'installer des traductions pour la langue anglaise (ou toute autre si nécessaire):

Sudo apt-get install language-pack-en

qui fournit des mises à jour des données de traduction pour tous les packages pris en charge (y compris Python).

Et assurez-vous d'utiliser le bon encodage dans votre code.

Par exemple:

open(foo, encoding='utf-8')

Vérifiez ensuite la configuration de votre système comme la valeur de LANG ou la configuration des paramètres régionaux (/etc/default/locale) et n'oubliez pas de vous reconnecter à votre session.

0
kenorb