it-swarm.com.de

Behebung: "UnicodeDecodeError: Codec" ascii "kann Byte nicht decodieren"

as3:~/ngokevin-site# nano content/blog/20140114_test-chinese.mkd
as3:~/ngokevin-site# wok
Traceback (most recent call last):
File "/usr/local/bin/wok", line 4, in
Engine()
File "/usr/local/lib/python2.7/site-packages/wok/engine.py", line 104, in init
self.load_pages()
File "/usr/local/lib/python2.7/site-packages/wok/engine.py", line 238, in load_pages
p = Page.from_file(os.path.join(root, f), self.options, self, renderer)
File "/usr/local/lib/python2.7/site-packages/wok/page.py", line 111, in from_file
page.meta['content'] = page.renderer.render(page.original)
File "/usr/local/lib/python2.7/site-packages/wok/renderers.py", line 46, in render
return markdown(plain, Markdown.plugins)
File "/usr/local/lib/python2.7/site-packages/markdown/init.py", line 419, in markdown
return md.convert(text)
File "/usr/local/lib/python2.7/site-packages/markdown/init.py", line 281, in convert
source = unicode(source)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 1: ordinal not in range(128). -- Note: Markdown only accepts unicode input!

Wie man es repariert?

In einigen anderen Python-basierten statischen Blog-Apps kann der chinesische Beitrag erfolgreich veröffentlicht werden. __ Wie diese App: http://github.com/vrypan/bucket3 Auf meiner Website http://bc3.brite.biz/ kann der chinesische Beitrag erfolgreich veröffentlicht werden.

350
fisherman

tl; dr/quick fix

  • Dekodieren/kodieren Sie nicht ohne Grund
  • Gehen Sie nicht davon aus, dass Ihre Zeichenfolgen UTF-8-codiert sind
  • Versuchen Sie, Zeichenfolgen so schnell wie möglich in Unicode-Zeichenfolgen zu konvertieren
  • Korrigieren Sie Ihr Gebietsschema: Wie löse ich UnicodeDecodeError in Python 3.6?
  • Seien Sie nicht versucht, schnelle reload - Hacks zu verwenden

Unicode-Zen in Python 2.x - Die Langversion

Ohne die Quelle zu sehen, ist es schwierig, die Grundursache zu kennen, also muss ich allgemein sprechen.

UnicodeDecodeError: 'ascii' codec can't decode byte Tritt im Allgemeinen auf, wenn Sie versuchen, ein Python 2.x str, das Nicht-ASCII-Zeichenfolgen enthält, in eine Unicode-Zeichenfolge zu konvertieren, ohne die Codierung der ursprünglichen Zeichenfolge anzugeben.

Kurz gesagt, Unicode-Zeichenfolgen sind ein völlig separater Typ von Python-Zeichenfolgen, der keine Codierung enthält. Sie enthalten nur Unicode Punktcodes und können daher jeden Unicode-Punkt aus dem gesamten Spektrum enthalten. Strings enthalten kodierten Text, also UTF-8, UTF-16, ISO-8895-1, GBK, Big5 usw. Strings werden in Unicode dekodiert und Unicodes werden in Strings kodiert. Dateien und Textdaten werden immer in codierten Zeichenfolgen übertragen.

Die Autoren des Markdown-Moduls verwenden wahrscheinlich unicode() (bei dem die Ausnahme ausgelöst wird) als Qualitätsgatter für den Rest des Codes - es konvertiert ASCII oder bricht vorhandene Unicode-Zeichenfolgen in a um neue Unicode-Zeichenfolge. Die Markdown-Autoren können die Codierung der eingehenden Zeichenfolge nicht kennen. Daher müssen Sie die Zeichenfolgen vor der Übergabe an Markdown in Unicode-Zeichenfolgen decodieren.

Unicode-Zeichenfolgen können in Ihrem Code mit dem Präfix u für Zeichenfolgen deklariert werden. Z.B.

>>> my_u = u'my ünicôdé strįng'
>>> type(my_u)
<type 'unicode'>

Unicode-Zeichenfolgen können auch aus Dateien, Datenbanken und Netzwerkmodulen stammen. In diesem Fall müssen Sie sich keine Gedanken über die Kodierung machen.

Fallstricke

Die Konvertierung von str nach Unicode kann auch dann erfolgen, wenn Sie unicode() nicht explizit aufrufen.

Die folgenden Szenarien verursachen UnicodeDecodeError Ausnahmen:

# Explicit conversion without encoding
unicode('€')

# New style format string into Unicode string
# Python will try to convert value string to Unicode first
u"The currency is: {}".format('€')

# Old style format string into Unicode string
# Python will try to convert value string to Unicode first
u'The currency is: %s' % '€'

# Append string to Unicode
# Python will try to convert string to Unicode first
u'The currency is: ' + '€'         

Beispiele

In der folgenden Abbildung sehen Sie, wie das Wort café Je nach Terminaltyp entweder in "UTF-8" - oder "Cp1252" -Codierung codiert wurde. In beiden Beispielen ist caf nur regulärer ASCII-Wert. In UTF-8 wird é Mit zwei Bytes codiert. In "Cp1252" ist é 0xE9 (was auch der Unicode-Punktwert ist (es ist kein Zufall)). Die richtige decode() wird aufgerufen und die Konvertierung in ein Python Unicode ist erfolgreich: Diagram of a string being converted to a Python Unicode string

In diesem Diagramm wird decode() mit ascii aufgerufen (das entspricht dem Aufruf von unicode() ohne Angabe einer Codierung). Da ASCII keine Bytes größer als 0x7F Enthalten kann, wird eine UnicodeDecodeError - Ausnahme ausgelöst:

Diagram of a string being converted to a Python Unicode string with the wrong encoding

Das Unicode-Sandwich

Es wird empfohlen, in Ihrem Code ein Unicode-Sandwich zu erstellen, in dem Sie alle eingehenden Daten in Unicode-Zeichenfolgen dekodieren, mit Unicodes arbeiten und dann auf dem Weg nach draußen in str s kodieren. Dies erspart Ihnen die Sorge um die Kodierung von Zeichenfolgen in der Mitte Ihres Codes.

Eingabe/Decodierung

Quellcode

Wenn Sie Nicht-ASCII in Ihren Quellcode einbinden müssen, erstellen Sie einfach Unicode-Zeichenfolgen, indem Sie der Zeichenfolge ein u voranstellen. Z.B.

u'Zürich'

Damit Python Ihren Quellcode dekodieren kann, müssen Sie einen Kodierungsheader hinzufügen, der der tatsächlichen Kodierung Ihrer Datei entspricht. Wenn Ihre Datei beispielsweise als "UTF-8" codiert wurde, würden Sie Folgendes verwenden:

# encoding: utf-8

Dies ist nur erforderlich, wenn Sie Nicht-ASCII in Ihrem Quellcode haben.

Dateien

Normalerweise werden Nicht-ASCII-Daten aus einer Datei empfangen. Das Modul io bietet einen TextWrapper, der Ihre Datei im Handumdrehen unter Verwendung einer vorgegebenen encoding dekodiert. Sie müssen die richtige Kodierung für die Datei verwenden - dies kann nicht leicht erraten werden. Beispiel für eine UTF-8-Datei:

import io
with io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file:
     my_unicode_string = my_file.read() 

my_unicode_string Wäre dann für die Übergabe an Markdown geeignet. Wenn in der Zeile read() ein UnicodeDecodeError steht, haben Sie wahrscheinlich den falschen Codierungswert verwendet.

CSV-Dateien

Das CSV-Modul Python 2.7 unterstützt keine Nicht-ASCII-Zeichen ????. Hilfe gibt es jedoch mit https://pypi.python.org/pypi/backports.csv .

Verwenden Sie es wie oben, aber übergeben Sie die geöffnete Datei:

from backports import csv
import io
with io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file:
    for row in csv.reader(my_file):
        yield row

Datenbanken

Die meisten Python Datenbanktreiber können Daten in Unicode zurückgeben, erfordern jedoch normalerweise eine kleine Konfiguration. Verwenden Sie für SQL-Abfragen immer Unicode-Zeichenfolgen.

In der Verbindungszeichenfolge hinzufügen:

charset='utf8',
use_unicode=True

Z.B.

>>> db = MySQLdb.connect(Host="localhost", user='root', passwd='passwd', db='sandbox', use_unicode=True, charset="utf8")

Hinzufügen:

psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY)

HTTP

Webseiten können in nahezu jeder Codierung codiert werden. Der Content-type - Header sollte ein charset - Feld enthalten, um auf die Codierung hinzuweisen. Der Inhalt kann dann manuell anhand dieses Werts dekodiert werden. Alternativ liefert Python-Requests Unicodes in response.text.

Manuell

Wenn Sie Zeichenfolgen manuell dekodieren müssen, können Sie einfach my_string.decode(encoding) ausführen, wobei encoding die entsprechende Kodierung ist. Python 2.x unterstützte Codecs sind hier angegeben: Standard Encodings . Wenn Sie wieder UnicodeDecodeError erhalten, haben Sie wahrscheinlich die falsche Codierung.

Das Fleisch vom Sandwich

Arbeiten Sie mit Unicodes wie mit normalen Zeichenfolgen.

Ausgabe

stdout/druck

print schreibt durch den Standard-Stream. Python versucht, einen Encoder auf stdout so zu konfigurieren, dass Unicodes nach der Codierung der Konsole codiert werden. Wenn beispielsweise die locale einer Linux-Shell en_GB.UTF-8 Lautet, wird die Ausgabe in UTF-8 Codiert. Unter Windows sind Sie auf eine 8-Bit-Codepage beschränkt.

Eine falsch konfigurierte Konsole, z. B. ein beschädigtes Gebietsschema, kann zu unerwarteten Druckfehlern führen. Die Umgebungsvariable PYTHONIOENCODING kann die Kodierung für stdout erzwingen.

Dateien

Genau wie bei der Eingabe kann mit io.open Unicodes transparent in codierte Byte-Strings konvertiert werden.

Datenbank

Dieselbe Konfiguration zum Lesen ermöglicht das direkte Schreiben von Unicodes.

Python 3

Python 3 ist nicht mehr Unicode-fähig als Python 2.x, es ist jedoch etwas weniger verwirrt über das Thema. ZB ist die reguläre str jetzt eine Unicode-Zeichenfolge und die alte str ist jetzt bytes.

Die Standardkodierung ist UTF-8. Wenn Sie also .decode() eine Byte-Zeichenfolge ohne Kodierung angeben, verwendet Python 3 die UTF-8-Kodierung. Dies behebt wahrscheinlich 50% der Unicode-Probleme.

Darüber hinaus arbeitet open() standardmäßig im Textmodus, sodass dekodierte str (Unicode) zurückgegeben werden. Die Codierung wird von Ihrem Gebietsschema abgeleitet, das auf Un * x-Systemen in der Regel UTF-8 oder auf Windows-Boxen eine 8-Bit-Codepage wie Windows-1251 ist.

Warum Sie sys.setdefaultencoding('utf8') nicht verwenden sollten

Es ist ein übler Hack (es gibt einen Grund, warum Sie reload verwenden müssen), der nur Probleme maskiert und Ihre Migration nach Python 3.x behindert. Verstehe das Problem, behebe die Ursache und genieße Unicode Zen. Siehe Warum sollten wir NICHT sys.setdefaultencoding ("utf-8") in einem Py-Skript verwenden? für weitere Details

515

Endlich hab ich es:

as3:/usr/local/lib/python2.7/site-packages# cat sitecustomize.py
# encoding=utf8  
import sys  

reload(sys)  
sys.setdefaultencoding('utf8')

Lass mich das überprüfen:

as3:~/ngokevin-site# python
Python 2.7.6 (default, Dec  6 2013, 14:49:02)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> reload(sys)
<module 'sys' (built-in)>
>>> sys.getdefaultencoding()
'utf8'
>>>

Das obige zeigt, dass die Standardkodierung von Python utf8 ist. Dann ist der Fehler nicht mehr.

473
fisherman

Dies ist das klassische "Unicode-Problem". Ich glaube, dass dies zu erklären, würde den Rahmen einer StackOverflow-Antwort übersteigen, um vollständig zu erklären, was passiert. 

Es ist gut erklärt hier .

In einer kurzen Zusammenfassung haben Sie etwas übergeben, das als Bytefolge an etwas interpretiert wird, das es in Unicode-Zeichen decodieren muss, aber der Standardcodec (ASCII) schlägt fehl.

Die Präsentation, auf die ich Sie hingewiesen habe, gibt Hinweise, um dies zu vermeiden. Machen Sie aus Ihrem Code ein "Unicode-Sandwich". In Python 2 hilft die Verwendung von "from __future__ import unicode_literals".

Update: wie kann der Code behoben werden:

OK - in Ihrer Variable "source" haben Sie einige Bytes. Es ist nicht klar aus Ihrer Frage, wie sie dort reingekommen sind - vielleicht haben Sie sie aus einem Webformular gelesen? In jedem Fall werden sie nicht mit ASCII codiert, aber Python versucht, sie in Unicode zu konvertieren, vorausgesetzt, sie sind es. Sie müssen explizit sagen, was die Kodierung ist. Dies bedeutet, dass Sie know wissen müssen, was die Kodierung ist! Das ist nicht immer einfach und hängt ganz davon ab, woher diese Saite stammt. Sie könnten mit einigen gängigen Kodierungen experimentieren, beispielsweise mit UTF-8. Sie teilen unicode () die Kodierung als zweiten Parameter mit:

source = unicode(source, 'utf-8')
119
GreenAsJade

Wenn Sie Ihre Standardcodierung (print sys.getdefaultencoding()) überprüfen, wird in einigen Fällen die Verwendung von ASCII zurückgegeben. Wenn Sie zu UTF-8 wechseln, funktioniert dies nicht, je nach dem Inhalt Ihrer Variablen. Ich habe einen anderen Weg gefunden: 

import sys
reload(sys)  
sys.setdefaultencoding('Cp1252')
38
Davy
"UnicodeDecodeError: 'ascii' codec can't decode byte"

Ursache für diesen Fehler: input_string muss Unicode sein, aber es wurde str angegeben

"TypeError: Decoding Unicode is not supported"

Ursache dieses Fehlers: Versuch, Unicode input_string in Unicode umzuwandeln


Überprüfen Sie daher zunächst, dass Ihr input_string str ist, und konvertieren Sie ggf. in Unicode:

if isinstance(input_string, str):
   input_string = unicode(input_string, 'utf-8')

Zweitens ändert das obige nur den Typ, entfernt jedoch keine ASCII-Zeichen. Wenn Sie Nicht-ASCII-Zeichen entfernen möchten:

if isinstance(input_string, str):
   input_string = input_string.decode('ascii', 'ignore').encode('ascii') #note: this removes the character and encodes back to string.

Elif isinstance(input_string, unicode):
   input_string = input_string.encode('ascii', 'ignore')
17

Ich habe nach folgender Fehlermeldung gesucht:

unicode-Codefehler: Codec 'ascii' kann Byte 0xe2 in Position 5454 nicht decodieren: Ordinalzahl nicht im Bereich (128)

Ich habe es endlich behoben, indem ich 'encoding' angegeben habe:

f = open('../glove/glove.6B.100d.txt', encoding="utf-8")

Ich wünschte, es könnte dir auch helfen.

15
Zoe L

Am besten ist es, immer in Unicode zu konvertieren - dies ist jedoch schwer zu erreichen, da Sie in der Praxis jedes Argument prüfen und in jede Funktion und Methode konvertieren müssen, die Sie jemals schreiben, die eine Form der String-Verarbeitung enthält.

Daher habe ich den folgenden Ansatz gefunden, um entweder Unicodes oder Byte-Zeichenfolgen aus beiden Eingaben zu garantieren. Kurz gesagt, Include und Use die folgenden Lambdas:

# guarantee unicode string
_u = lambda t: t.decode('UTF-8', 'replace') if isinstance(t, str) else t
_uu = lambda *tt: Tuple(_u(t) for t in tt) 
# guarantee byte string in UTF8 encoding
_u8 = lambda t: t.encode('UTF-8', 'replace') if isinstance(t, unicode) else t
_uu8 = lambda *tt: Tuple(_u8(t) for t in tt)

Beispiele:

text='Some string with codes > 127, like Zürich'
utext=u'Some string with codes > 127, like Zürich'
print "==> with _u, _uu"
print _u(text), type(_u(text))
print _u(utext), type(_u(utext))
print _uu(text, utext), type(_uu(text, utext))
print "==> with u8, uu8"
print _u8(text), type(_u8(text))
print _u8(utext), type(_u8(utext))
print _uu8(text, utext), type(_uu8(text, utext))
# with % formatting, always use _u() and _uu()
print "Some unknown input %s" % _u(text)
print "Multiple inputs %s, %s" % _uu(text, text)
# but with string.format be sure to always work with unicode strings
print u"Also works with formats: {}".format(_u(text))
print u"Also works with formats: {},{}".format(*_uu(text, text))
# ... or use _u8 and _uu8, because string.format expects byte strings
print "Also works with formats: {}".format(_u8(text))
print "Also works with formats: {},{}".format(*_uu8(text, text))

Hier sind noch einige Überlegungen dazu .

8
miraculixx

Encode konvertiert ein Unicode-Objekt in ein String-Objekt. Ich denke, Sie versuchen, ein String-Objekt zu codieren. Konvertieren Sie zunächst Ihr Ergebnis in ein Unicode-Objekt und kodieren Sie dieses Unicode-Objekt beispielsweise in 'utf-8' ..__

    result = yourFunction()
    result.decode().encode('utf-8')
5
RAFI AFRIDI

Ich hatte das gleiche Problem, aber es funktionierte nicht für Python 3. Ich folgte dem und löste mein Problem:

enc = sys.getdefaultencoding()
file = open(menu, "r", encoding = enc)

Sie müssen die Kodierung einstellen, wenn Sie die Datei lesen/schreiben.

3
Reihan_amn

Kurz gesagt, um eine korrekte Unicode-Behandlung in Python 2 sicherzustellen:

  • verwenden Sie io.open zum Lesen/Schreiben von Dateien
  • verwenden Sie from __future__ import unicode_literals
  • konfigurieren Sie andere Datenein-/ausgänge (z. B. Datenbanken, Netzwerk) für die Verwendung von Unicode
  • wenn Sie keine Ausgaben für utf-8 konfigurieren können, konvertieren Sie Ihre Ausgaben für diese print(text.encode('ascii', 'replace').decode()).

Erläuterungen finden Sie unter @Alastair McCormacks detaillierte Antwort .

2
idbrii

Ich hatte das gleiche Problem mit der Zeichenfolge "Pastelería Mallorca" und löste es mit:

unicode("Pastelería Mallorca", 'latin-1')
2
Alle Pavesi

Dieser Fehler tritt auf, wenn in unserer Zeichenfolge einige Zeichen ASCII enthalten sind und alle Operationen an dieser Zeichenfolge ohne ordnungsgemäße Dekodierung ausgeführt werden. Dies half mir, mein Problem zu lösen Spalten-ID, Text und Dekodierungszeichen wie folgt:

train_df = pd.read_csv("Example.csv")
train_data = train_df.values
for i in train_data:
    print("ID :" + i[0])
    text = i[1].decode("utf-8",errors="ignore").strip().lower()
    print("Text: " + text)
1
Sravya

In einem Django (1.9.10)/Python 2.7.5-Projekt habe ich häufige UnicodeDecodeError-Ausnahmen; hauptsächlich, wenn ich versuche, Unicode-Zeichenfolgen der Protokollierung zuzuführen. Ich habe eine Hilfsfunktion für beliebige Objekte erstellt, die im Wesentlichen in 8-Bit-ASCII-Zeichenfolgen formatiert und alle Zeichen, die nicht in der Tabelle enthalten sind, durch "?" Ersetzt. Ich denke, es ist nicht die beste Lösung, aber da die Standardcodierung ascii ist (und ich möchte sie nicht ändern), wird sie Folgendes tun:

 def encode_for_logging (c, coding = 'ascii'): 
 Wenninstanz (c, Basiszeichenfolge): 
 Rückgabe c.encode (Kodierung, 'ersetzen') 
 Elif isinstance (c, Iterable): 
 c_ = [] 
 für v in c: 
 c_.append (encode_for_logging (v, Kodierung)) 
 return c _
 sonst:
 return encode_for_logging (unicode (c)) 
`

1
Paul Bormans

Ich hatte den gleichen Fehler, mit URLs, die Nicht-ASCII-Zeichen enthalten (Bytes mit Werten> 128).

url = url.decode('utf8').encode('utf-8')

Hinweis: utf-8, utf8 sind einfach Aliase. Die Verwendung von 'utf8' oder 'utf-8' sollte auf dieselbe Weise funktionieren

In meinem Fall, der für mich in Python 2.7 ausgeführt wurde, hat diese Zuweisung vermutlich etwas in der str-internen Darstellung geändert - dh sie zwingt die richtige Decodierung der hinterlegten Bytefolge in url und setzt den String schließlich in eine. utf-8 str mit der ganzen Magie an der richtigen Stelle . Unicode in Python ist schwarze Magie für mich . Hoffnung nützlich

1
Fabiano Tarlao

Habe den gleichen Fehler und das hat meinen Fehler behoben. Vielen Dank! Python 2 und Python 3, die sich in der Unicode-Verarbeitung unterscheiden, machen die geladenen Dateien ziemlich inkompatibel. Verwenden Sie also das Codierungsargument von python pickle. Der folgende Link hat mir geholfen, das ähnliche Problem zu lösen, als ich versuchte, eingelesene Daten aus meinem Python 3.7 zu öffnen, während meine Datei ursprünglich in der Python 2.x-Version gespeichert war. https://blog.modest-destiny.com/posts/python-2-and-3-compatible-pickle-save-and-load/ Ich kopiere die Funktion load_pickle in mein Skript und rufe die Funktion load_pickle (pickle_file auf ) beim Laden meiner input_data wie folgt:

input_data = load_pickle("my_dataset.pkl")

Die load_pickle Funktion ist hier:

def load_pickle(pickle_file):
    try:
        with open(pickle_file, 'rb') as f:
            pickle_data = pickle.load(f)
    except UnicodeDecodeError as e:
        with open(pickle_file, 'rb') as f:
            pickle_data = pickle.load(f, encoding='latin1')
    except Exception as e:
        print('Unable to load data ', pickle_file, ':', e)
        raise
    return pickle_data
0
Ganesh Shah

Das hat bei mir funktioniert:

    file = open('docs/my_messy_doc.pdf', 'rb')
0
saran3h

Hier ist meine Lösung, fügen Sie einfach die Codierung. with open(file, encoding='utf8') as f

Und da das Lesen der Handschuhdatei sehr lange dauert, empfehle ich, die Handschuhdatei in eine numpy-Datei umzuwandeln. Wenn Sie die Einbettungsgewichte zur Netx-Zeit lesen, wird Ihre Zeit gespart.

import numpy as np
from tqdm import tqdm


def load_glove(file):
    """Loads GloVe vectors in numpy array.
    Args:
        file (str): a path to a glove file.
    Return:
        dict: a dict of numpy arrays.
    """
    embeddings_index = {}
    with open(file, encoding='utf8') as f:
        for i, line in tqdm(enumerate(f)):
            values = line.split()
            Word = ''.join(values[:-300])
            coefs = np.asarray(values[-300:], dtype='float32')
            embeddings_index[Word] = coefs

    return embeddings_index

# EMBEDDING_PATH = '../embedding_weights/glove.840B.300d.txt'
EMBEDDING_PATH = 'glove.840B.300d.txt'
embeddings = load_glove(EMBEDDING_PATH)

np.save('glove_embeddings.npy', embeddings) 

Hauptlink: https://Gist.github.com/BrambleXu/634a844cdd3cd04bb2e3ba3c83aef227

0
Bramble

Geben Sie Folgendes an: # coding = utf-8 am Anfang Ihrer Python-Datei. Das Problem sollte behoben werden

0

Um dies auf Betriebssystemebene in einer Ubuntu-Installation zu beheben, überprüfen Sie Folgendes:

$ locale charmap

Wenn du bekommst

locale: Cannot set LC_CTYPE to default locale: No such file or directory

anstatt

UTF-8

dann LC_CTYPE und LC_ALL wie folgt einstellen:

$ export LC_ALL="en_US.UTF-8"
$ export LC_CTYPE="en_US.UTF-8"
0
vervas