UnicodeEncodeError: Der Codec 'ascii' kann das Zeichen u '\ xef' an Position 0 nicht codieren: Ordnungszahl nicht im Bereich (128)

75

Ich möchte mein XML-Dokument analysieren. Daher habe ich mein XML-Dokument wie folgt gespeichert

class XMLdocs(db.Expando):  
   id = db.IntegerProperty()    
   name=db.StringProperty()  
   content=db.BlobProperty()  

Jetzt ist mein unten mein Code

parser = make_parser()     
curHandler = BasketBallHandler()  
parser.setContentHandler(curHandler)  
for q in XMLdocs.all():  
        parser.parse(StringIO.StringIO(q.content))

Ich erhalte unter Fehler

'ascii' codec can't encode character u'\xef' in position 0: ordinal not in range(128)
Traceback (most recent call last):  
  File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/webapp/__init__.py", line 517, in __call__
    handler.post(*groups)   
  File "/base/data/home/apps/parsepython/1.348669006354245654/mapreduce/base_handler.py", line 59, in post
    self.handle()   
  File "/base/data/home/apps/parsepython/1.348669006354245654/mapreduce/handlers.py", line 168, in handle
    scan_aborted = not self.process_entity(entity, ctx)   
  File "/base/data/home/apps/parsepython/1.348669006354245654/mapreduce/handlers.py", line 233, in process_entity
    handler(entity)   
  File "/base/data/home/apps/parsepython/1.348669006354245654/parseXML.py", line 71, in process
    parser.parse(StringIO.StringIO(q.content))   
  File "/base/python_runtime/python_dist/lib/python2.5/xml/sax/expatreader.py", line 107, in parse
    xmlreader.IncrementalParser.parse(self, source)   
  File "/base/python_runtime/python_dist/lib/python2.5/xml/sax/xmlreader.py", line 123, in parse
    self.feed(buffer)  
  File "/base/python_runtime/python_dist/lib/python2.5/xml/sax/expatreader.py", line 207, in feed
    self._parser.Parse(data, isFinal)   
  File "/base/data/home/apps/parsepython/1.348669006354245654/parseXML.py", line 136, in characters   
    print ch   
UnicodeEncodeError: 'ascii' codec can't encode character u'\xef' in position 0: ordinal not in range(128)   
Mahesh
quelle
2
Ihr Stacktrace zeigt, dass sich Ihr ausführender Code von dem unterscheidet, den Sie eingefügt haben - und dass Sie ihn verwenden print. Verwenden Sie print nicht in einer WSGI-App!
Nick Johnson

Antworten:

30

Es scheint, dass Sie eine UTF-8-Byte-Bestellmarke (BOM) treffen. Versuchen Sie, diese Unicode-Zeichenfolge mit extrahierter Stückliste zu verwenden:

import codecs

content = unicode(q.content.strip(codecs.BOM_UTF8), 'utf-8')
parser.parse(StringIO.StringIO(content))

Ich habe stripanstelle von verwendet, lstripweil in Ihrem Fall mehrere Stücklisten aufgetreten sind, möglicherweise aufgrund von verketteten Dateiinhalten.

Tugrul Ates
quelle
Ich habe genau das getan, was in der Antwort erwähnt wurde, aber den obigen Fehler erhalten. Zuerst gab es mich auf Position 0, die in Frage gestellt wurde, und jetzt gibt es mir auf Position 5785, die im vorherigen Kommentar erwähnt wurde
Mahesh
Ich empfehle, jeden String zu konvertieren, sder den Fehler mit erzeugt s = unicode(s.strip(codecs.BOM_UTF8), 'utf-8'). sbezieht sich auf den Namen Ihrer Zeichenfolgen.
Tugrul Ates
Versuchen Sie zu ersetzen lstripmit strip.
Tugrul Ates
Ich verstehe, was Sie vorschlagen, und ich habe den gleichen Fehler im Detail gemacht: ascii 'Codec kann das Zeichen u' \ xef 'in Position 5785 nicht codieren: Ordnungszahl nicht im Bereich (128)
Mahesh
1
Es ist ein Codierungsfehler während der Konvertierung eines Unicodes in einen String während des Druckens. Es enthält keine UTF-8-Stückliste, kann nicht zurück in Unicode dekodiert werden. Der Fehler besteht darin, dass Nicht-ASCII-Zeichen gezählt werden. Wenn Sie diese entfernen , wird der Inhalt beschädigt , und die Stückliste ist nur eine davon.
Rosh Oxymoron
112

Die beste Antwort auf dieses Problem hängt von Ihrer Umgebung ab, insbesondere davon, welche Codierung Ihr Terminal erwartet.

Die schnellste einzeilige Lösung besteht darin, alles, was Sie drucken, in ASCII zu codieren, was Ihr Terminal mit ziemlicher Sicherheit akzeptiert, und Zeichen zu verwerfen, die Sie nicht drucken können:

print ch #fails
print ch.encode('ascii', 'ignore')

Die bessere Lösung besteht darin, die Codierung Ihres Terminals in utf-8 zu ändern und vor dem Drucken alles als utf-8 zu codieren. Sie sollten es sich zur Gewohnheit machen, jedes Mal, wenn Sie eine Zeichenfolge drucken oder lesen, über Ihre Unicode-Codierung nachzudenken.

Triptychon
quelle
1
In meinem Fall druckte ich einen Twitter-Stream auf ein Terminal und es funktionierte einwandfrei. Dann wollte ich die Programmausgabe in eine Datei umleiten. Ich bekam den Codec 'ascii', der keine Zeichen an Position 32-36 codieren kann. Später, wie in dieser Antwort, habe ich print tweet.encode ("utf-8", ignorieren) verwendet, und alles hat funktioniert.
kommradHomer
57

Nur .encode('utf-8')am Ende des Objekts zu setzen, erledigt den Job in neueren Versionen von Python.

Nicole
quelle
3
Was meinst du mit "aktuellen Versionen von Python"? Nur 3.xoder auch 2.7?
kramer65
1
Python 2.7 ist eindeutig neu, da es immer noch weit verbreitet ist.
tmthyjames
1
Funktioniert für mich auf Python 2.7
A Star
30

Das hat bei mir funktioniert:

from django.utils.encoding import smart_str
content = smart_str(content)
Orlando Pozo
quelle
8

Das Problem gemäß Ihrem Traceback ist die printAussage in Zeile 136 von parseXML.py. Leider haben Sie es nicht für angebracht gehalten, diesen Teil Ihres Codes zu veröffentlichen, aber ich gehe davon aus, dass er nur zum Debuggen da ist. Wenn Sie es ändern zu:

print repr(ch)

dann sollten Sie zumindest sehen, was Sie drucken möchten.

Duncan
quelle
2
-1 für eine Nicht-Unicode-Lösung für ein offensichtliches Unicode-Codierungsproblem.
Triptychon
7
Das Unicode-Codierungsproblem liegt bei der print-Anweisung. Ja, es kann andere Probleme geben, aber das Problem, dass der Druck nicht abstürzt, ist das unmittelbare Problem.
Duncan
7

Das Problem ist, dass Sie versuchen, ein Unicode-Zeichen auf ein möglicherweise nicht Unicode-Terminal zu drucken. Sie müssen es mit der 'replaceOption codieren, bevor Sie es drucken, z print ch.encode(sys.stdout.encoding, 'replace').

Rosh Oxymoron
quelle
Drucken ist nicht wesentlich, die Hauptaussage für mich, wo ich Fehler
erhalte
3
@ Mahesh: Es ist IHR Code, der das Problem verursacht, in Zeile 136 von parseXML.py - entweder selbst beheben oder uns diesen Teil des Codes zeigen, damit wir Ihnen helfen können.
John Machin
-1

Eine einfache Lösung, um dieses Problem zu beheben, besteht darin, die Standardcodierung auf utf8 festzulegen. Folgen ist ein Beispiel

import sys

reload(sys)
sys.setdefaultencoding('utf8')
Shafiq
quelle
Mach das nicht. warum es Code bricht
Mark Tolonen
Können Sie den Grund erklären?
Shafiq
In meinem Kommentar befindet sich ein Link, der dies erklärt. Im Wesentlichen erwarten Bibliotheken, dass der Standardwert der Standard asciibleibt. Deshalb setdefaultencodingist es normalerweise nicht ohne den reloadTrick verfügbar .
Mark Tolonen