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

1296

Ich habe Probleme mit Unicode-Zeichen aus Text, der von verschiedenen Webseiten (auf verschiedenen Websites) abgerufen wurde. Ich benutze BeautifulSoup.

Das Problem ist, dass der Fehler nicht immer reproduzierbar ist. es funktioniert manchmal mit einigen Seiten, und manchmal barfs es, indem es ein wirft UnicodeEncodeError. Ich habe so gut wie alles versucht, was mir einfällt, und dennoch nichts gefunden, das konsistent funktioniert, ohne einen Unicode-Fehler auszulösen.

Einer der Codeabschnitte, die Probleme verursachen, ist unten dargestellt:

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()

Hier ist eine Stapelverfolgung, die für einige Zeichenfolgen erstellt wird, wenn das obige Snippet ausgeführt wird:

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)

Ich vermute, dass dies daran liegt, dass einige Seiten (oder genauer gesagt Seiten von einigen Websites) möglicherweise codiert sind, während andere möglicherweise nicht codiert sind. Alle Websites haben ihren Sitz in Großbritannien und bieten Daten, die für den Verbrauch in Großbritannien bestimmt sind. Es gibt also keine Probleme im Zusammenhang mit der Internalisierung oder dem Umgang mit Texten, die nicht in Englisch verfasst sind.

Hat jemand irgendwelche Ideen, wie man das löst, damit ich dieses Problem konsequent beheben kann?

Homunculus Reticulli
quelle
1
Wenn Sie diese Fehler als Benutzer und nicht als Entwickler erhalten, überprüfen Sie serverfault.com/questions/54591/… und askubuntu.com/questions/599808/…
That Brazilian Guy
Ich werde diesen Punkt hinzufügen, benutze nicht onlinegdb.com/online_python_interpreter für dieses Zeug. Ich habe diesen Interpreter verwendet, um Dinge auszuprobieren, und er ist für Unicode nicht richtig konfiguriert! Druckte immer in einem Format 'B' \ nnn '' ... als ich nur ein Guillemet wollte! Versucht auf einer VM und es funktionierte sofort wie erwartet mit chr ()
JGFMK
4
Versuche dies import os; import locale; os.environ["PYTHONIOENCODING"] = "utf-8"; myLocale=locale.setlocale(category=locale.LC_ALL, locale="en_GB.UTF-8"); ... print(myText.encode('utf-8', errors='ignore')) .
hhh
@hhh Ich habe Ihr Snippet NameError ausgeführt: Name 'myText' ist nicht definiert
KHAN irfan
9
Versuchen Sie, PYTHONIOENCODING in der Shell festzulegen , bevor Sie Ihr Skript ausführen:$ export PYTHONIOENCODING=utf8
Noam Manos

Antworten:

1362

Sie müssen das Python Unicode HOWTO lesen . Dieser Fehler ist das allererste Beispiel .

Stoppen Sie grundsätzlich die strKonvertierung von Unicode in codierten Text / Bytes.

Verwenden Sie stattdessen ordnungsgemäß .encode(), um die Zeichenfolge zu codieren:

p.agent_info = u' '.join((agent_contact, agent_telno)).encode('utf-8').strip()

oder arbeiten vollständig in Unicode.

agf
quelle
23
einverstanden! Eine gute Faustregel, die mir beigebracht wurde, ist die Verwendung der Idee "Unicode-Sandwich". Ihr Skript akzeptiert Bytes von der Außenwelt, aber die gesamte Verarbeitung sollte in Unicode erfolgen. Nur wenn Sie bereit sind, Ihre Daten auszugeben, sollten sie wieder in Bytes umgewandelt werden!
Andbdrew
256
Für den Fall, dass jemand anderes dadurch verwirrt wird, habe ich eine seltsame Sache gefunden: Mein Terminal verwendet utf-8, und wenn ich printmeine utf-8-Zeichenfolgen verwende, funktioniert es gut. Wenn ich jedoch die Ausgabe meiner Programme in eine Datei leite, wird a ausgelöst UnicodeEncodeError. In der Tat, wenn die Ausgabe umgeleitet wird (in eine Datei oder eine Pipe), finde ich das sys.stdout.encodingist None! Das Anheften .encode('utf-8')löst das Problem.
Drevicko
93
@drevicko: Verwenden Sie PYTHONIOENCODING=utf-8stattdessen dh, drucken Sie Unicode-Zeichenfolgen und lassen Sie die Umgebung die erwartete Codierung festlegen.
JFS
1
@steinar: nichts ist in jedem fall gültig. Im Allgemeinen sollte es einem Benutzer egal sein, dass Sie Python zur Implementierung Ihres Dienstprogramms verwenden (die Benutzeroberfläche sollte sich nicht ändern, wenn Sie sich aus irgendeinem Grund für eine erneute Implementierung in einer anderen Sprache entscheiden), und Sie sollten daher nicht erwarten, dass dieser Benutzer überhaupt Kenntnis von Python hat. spezifische Envvars. Es ist eine schlechte Benutzeroberfläche, den Benutzer zu zwingen, die Zeichenkodierung anzugeben. Betten Sie die Zeichenkodierung bei Bedarf in das Berichtsformat ein. Hinweis: Keine fest codierte Codierung kann im allgemeinen Fall "sinnvoller Standard" sein.
JFS
13
Dies ist ein schlechter und verwirrender Rat. Der Grund, warum Leute str verwenden, ist, dass das Objekt NICHT bereits ein String ist, daher gibt es keine .encode()Methode zum Aufrufen.
Cerin
434

Dies ist ein klassischer Python-Unicode-Schmerzpunkt! Folgendes berücksichtigen:

a = u'bats\u00E0'
print a
 => batsà

Bis jetzt alles gut, aber wenn wir str (a) nennen, wollen wir sehen, was passiert:

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, das wird niemandem nützen! Um den Fehler zu beheben, codieren Sie die Bytes explizit mit .encode und teilen Sie Python mit, welcher Codec verwendet werden soll:

a.encode('utf-8')
 => 'bats\xc3\xa0'
print a.encode('utf-8')
 => batsà

Voil \ u00E0!

Das Problem ist, dass Python beim Aufrufen von str () die Standardzeichencodierung verwendet, um zu versuchen, die von Ihnen angegebenen Bytes zu codieren. In Ihrem Fall handelt es sich manchmal um Darstellungen von Unicode-Zeichen. Um das Problem zu beheben, müssen Sie Python mit .encode ('Whatever_unicode') mitteilen, wie mit der von Ihnen angegebenen Zeichenfolge umgegangen werden soll. Meistens sollten Sie mit utf-8 in Ordnung sein.

Eine hervorragende Darstellung zu diesem Thema finden Sie im PyCon-Vortrag von Ned Batchelder hier: http://nedbatchelder.com/text/unipain.html

Andbdrew
quelle
85
Persönlicher Hinweis: Wenn Sie versuchen, ".encode" einzugeben, geben Sie nicht versehentlich ".unicode" ein und fragen Sie sich, warum nichts funktioniert.
Überspringen Sie Huffman
9
Guter Rat. Aber was machen Sie stattdessen, wenn Sie str (x) zum Drucken von Objekten verwendet haben, die Zeichenfolgen sein können oder nicht? str (x) funktioniert, wenn x eine Zahl, ein Datum, eine Uhrzeit, ein Boolescher Wert oder ein normaler String ist. Wenn es ein Unicode ist, funktioniert es plötzlich nicht mehr. Gibt es eine Möglichkeit, dasselbe Verhalten zu erzielen, oder müssen wir jetzt eine IF-Prüfung hinzufügen, um zu testen, ob das Objekt eine Zeichenfolge für die Verwendung von .encode und andernfalls str () ist?
Dirk R
Dieselbe Frage könnte mit NoneWert gestellt werden.
Vadorequest
210

Ich fand elegante Arbeit für mich, um Symbole zu entfernen und weiterhin Zeichenfolge als Zeichenfolge wie folgt beizubehalten:

yourstring = yourstring.encode('ascii', 'ignore').decode('ascii')

Es ist wichtig zu beachten, dass die Verwendung der Option "Ignorieren" gefährlich ist, da dadurch die Unterstützung für Unicode (und Internationalisierung) stillschweigend aus dem Code entfernt wird, der sie verwendet (siehe Unicode konvertieren):

>>> u'City: Malmö'.encode('ascii', 'ignore').decode('ascii')
'City: Malm'
Max Korolevsky
quelle
17
Du hast meinen Tag gerettet! Für utf-8 ist es ausreichend zu tun:yourstring = yourstring.encode('utf-8', 'ignore').decode('utf-8')
luca76
Für mich hat das funktioniert, aber mein Fall war anders, ich habe Dateinamen gespeichert und hatte "/" im Namen und der Pfad war nicht vorhanden, also muss ich .replace ("/", "") verwenden und somit speichern mein Skript. Das Ignorieren des ASCII funktioniert auch für den Fall 'utf-8'.
Akash Kandpal
1
@ harrypotter0 für die korrekte Verkettung von Dateipfaden os.path.join()ist eine sehr gute Angewohnheit, wenn Sie mit der plattformübergreifenden Programmierung beginnen. :)
login_not_failed
152

Nun, ich habe alles versucht, aber es hat nicht geholfen. Nachdem ich herumgegoogelt hatte, dachte ich mir Folgendes und es half. Python 2.7 wird verwendet.

# encoding=utf8
import sys
reload(sys)
sys.setdefaultencoding('utf8')
Ashwin
quelle
7
Tu das nicht. stackoverflow.com/questions/3828723/… , obwohl, wenn Sie Antworten wie diese haben, stackoverflow.com/a/31137935/2141635 am oberen Rand der Ergebnisse, wenn Sie nach dem Fehler suchen, ich sehen kann, warum es eine gute Idee zu sein scheint.
Padraic Cunningham
21
Ich habe fast alle Vorschläge in diesem Thema ausprobiert und wirklich keiner hat für mich funktioniert. Endlich habe ich es versucht. Und es ist wirklich DAS EINZIGE, was einfach und gut funktioniert hat. Wenn jemand sagt "Tu das nicht, dann komm mit einer einfachen Lösung. Andernfalls benutze diese. Weil es eine gute Arbeitskopie und eine frühere Lösung ist.
Richard de Ree
4
Wie könnte das in Python3 gemacht werden? Würde mich freuen zu wissen.
Kanerva Peter
3
Nach so viel Frust funktionierte dieser. Vielen Dank.
Avraham Zhurba
4
Ich möchte nur einen hinzufügenif sys.version_info.major < 3:
Prof. Falken Vertrag verletzt
87

Ein subtiles Problem, das dazu führt, dass selbst der Druck fehlschlägt, besteht darin, dass Ihre Umgebungsvariablen falsch eingestellt sind, z. hier LC_ALL auf "C" gesetzt. In Debian raten sie davon ab, es einzustellen : Debian-Wiki im Gebietsschema

$ 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à
maxpolk
quelle
Ich habe genau das gleiche Problem, so schlimm, dass ich es vor der Berichterstattung nicht überprüft habe . Vielen Dank. Übrigens können Sie die ersten beiden Befehle durch ersetzen env|grep -E '(LC|LANG)'.
Dmitry Verhoturov
Nur meine zwei Cent wegen falscher Codierung. Ich benutze häufig mcim "Subshell-Modus" ( Ctrl-O) und habe auch vergessen, dass ich den folgenden Alias ​​zu bash hinzugefügt habe : alias mc="LANG=en_EN.UTF-8 mc". Wenn ich also versuchte, schlecht geschriebene Skripte auszuführen, die ru_RU.UTF-8intern verwendet werden, sterben sie einfach. Versuchte viele Sachen aus diesem Thread, bevor ich das eigentliche Problem entdeckte. :)
login_not_failed
DU BIST TOLL. In GSUTIL schlug mein rsync aufgrund genau dieses Problems fehl. Das LC_ALL wurde behoben und alles funktioniert gut als Wein. <3 DANKE <3
dsignr
27

Für mich hat funktioniert:

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

Hoffe das hilft jemandem.

Animesh
quelle
25

Ich habe tatsächlich festgestellt, dass es in den meisten Fällen viel einfacher ist, nur diese Zeichen zu entfernen:

s = mystring.decode('ascii', 'ignore')
Phil LaNasa
quelle
26
"Perfekt" ist normalerweise nicht das, was es leistet. Es wirft Dinge weg, mit denen Sie herausfinden sollten, wie Sie richtig umgehen sollen.
Tripleee
7
Nur "diese" (nicht englischen) Zeichen zu entfernen, ist nicht die Lösung, da Python alle Sprachen unterstützen muss, nicht wahr?
Alemol
8
Abgestimmt. Dies ist überhaupt nicht die richtige Lösung. Erfahren Sie, wie Sie mit Unicode arbeiten: joelonsoftware.com/articles/Unicode.html
Andrew Ferrier
4
Schauen Sie, die vernünftigste Art, diese spezielle Antwort zu präsentieren, ist folgende: Erkennen, dass ASCII bestimmten Sprachen und Benutzern ein bestimmtes Privileg verleiht - dies ist die Notluke , die für Benutzer ausgenutzt werden kann, die möglicherweise einen flüchtigen ersten Durchgang hacken , Skript zusammen möglicherweise für Vorarbeiten, bevor die vollständige Unicode-Unterstützung implementiert wird.
lol
5
Wenn ich ein Skript schreibe, das nur englischen Text drucken muss, um in einer internen Unternehmensanwendung zu standardisieren, möchte ich nur, dass das Problem behoben wird. Was auch immer funktioniert.
Kagronick
25

Das Problem ist, dass Sie versuchen, ein Unicode-Zeichen zu drucken, Ihr Terminal dies jedoch nicht unterstützt.

Sie können versuchen, das language-pack-enPaket zu installieren, um Folgendes zu beheben:

sudo apt-get install language-pack-en

Hier werden Aktualisierungen der englischen Übersetzungsdaten für alle unterstützten Pakete (einschließlich Python) bereitgestellt. Installieren Sie bei Bedarf ein anderes Sprachpaket (abhängig davon, welche Zeichen Sie drucken möchten).

Bei einigen Linux-Distributionen ist dies erforderlich, um sicherzustellen, dass die englischen Standard-Gebietsschemas ordnungsgemäß eingerichtet sind (damit Unicode-Zeichen von Shell / Terminal verarbeitet werden können). Manchmal ist es einfacher, es zu installieren, als es manuell zu konfigurieren.

Stellen Sie dann beim Schreiben des Codes sicher, dass Sie die richtige Codierung in Ihrem Code verwenden.

Zum Beispiel:

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

Wenn Sie immer noch ein Problem haben, überprüfen Sie Ihre Systemkonfiguration wie folgt:

  • Ihre Gebietsschemadatei ( /etc/default/locale), die z

    LANG="en_US.UTF-8"
    LC_ALL="en_US.UTF-8"

    oder:

    LC_ALL=C.UTF-8
    LANG=C.UTF-8
  • Wert von LANG/ LC_CTYPEin der Shell.

  • Überprüfen Sie, welches Gebietsschema Ihre Shell unterstützt:

    locale -a | grep "UTF-8"

Demonstration des Problems und der Lösung in einer neuen VM.

  1. Initialisieren und Bereitstellen der VM (z. B. mithilfe vagrant):

    vagrant init ubuntu/trusty64; vagrant up; vagrant ssh

    Siehe: verfügbare Ubuntu-Boxen . .

  2. Drucken von Unicode-Zeichen (z. B. Markenzeichen ):

    $ 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. Jetzt installieren 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. Jetzt sollte das Problem gelöst sein:

    $ python -c 'print(u"\u2122");'
    
  5. Versuchen Sie andernfalls den folgenden Befehl:

    $ LC_ALL=C.UTF-8 python -c 'print(u"\u2122");'
    
Kenorb
quelle
1
Was hat language-pack-enmit Python oder dieser Frage zu tun? AFAIK, es kann Sprachübersetzungen für Nachrichten bereitstellen, hat aber nichts mit Codierung zu tun
Alastair McCormack
2
Bei einigen Linux-Distributionen ist dies erforderlich, um sicherzustellen, dass die englischen Standardgebietsschemas ordnungsgemäß eingerichtet sind, insbesondere wenn das Python-Skript auf dem Terminal ausgeführt wird. Es hat an einem Punkt für mich funktioniert. Siehe: Zeichenkodierung
Kenorb
Ah, ok. Sie meinen, wenn Sie ein nicht englisches Gebietsschema verwenden möchten? Ich denke, der Benutzer muss auch bearbeiten, /etc/locale.genum sicherzustellen, dass sein Gebietsschema erstellt wird, bevor er es verwendet.
Alastair McCormack
1
@AlastairMcCormack Auskommentiert LANGvon /etc/default/locale(da /etc/locale.gennicht vorhanden) und ausgeführt locale-gen, aber es hat nicht geholfen. Ich bin mir nicht sicher, was language-pack-engenau funktioniert, da ich nicht viel Dokumentation gefunden habe und das Auflisten des Inhalts nicht viel hilft.
Kenorb
1
es ist unwahrscheinlich , dass es bereits das heißt kein utf-8 - Locales auf einem Desktop - System ist, ist es wahrscheinlich , dass Sie brauchen nichts zu installieren, einfach zu konfigurieren LANG/ LC_CTYPE/ LC_ALLstatt ( zum Beispiel LANG=C.UTF-8).
JFS
19

In der Schale:

  1. Suchen Sie das unterstützte UTF-8-Gebietsschema mit dem folgenden Befehl:

    locale -a | grep "UTF-8"
  2. Exportieren Sie es, bevor Sie das Skript ausführen, z.

    export LC_ALL=$(locale -a | grep UTF-8)

    oder manuell wie:

    export LC_ALL=C.UTF-8
  3. Testen Sie es, indem Sie ein Sonderzeichen drucken, z .

    python -c 'print(u"\u2122");'

Oben in Ubuntu getestet.

Kenorb
quelle
Ja, dies ist die beste kurze Antwort. Wir können den Quellcode nicht ändern, um .encode
Luat Nguyen - Neo.Mxn0 zu verwenden.
16

Fügen Sie unten am Anfang Ihres Skripts (oder als zweite Zeile) eine Zeile hinzu:

# -*- coding: utf-8 -*-

Das ist die Definition der Python-Quellcode-Codierung. Weitere Infos in PEP 263 .

Andriy Ivaneyko
quelle
2
Dies löst das Problem nicht, wenn verarbeiteter Text, der aus einer externen Datei geladen wurde, utf-8-Codierungen enthält. Dies hilft nur für Literale, die im angegebenen Python-Skript selbst geschrieben sind, und ist nur ein Hinweis für den Python-Interpreter, hat jedoch keine Auswirkungen auf die Textverarbeitung.
Mikaelblomkvistsson
16

Hier ist eine Wiederholung einiger anderer sogenannter "Cop-out" -Antworten. Es gibt Situationen, in denen es trotz der hier geäußerten Proteste eine gute Lösung ist, die lästigen Charaktere / Saiten einfach wegzuwerfen.

def safeStr(obj):
    try: return str(obj)
    except UnicodeEncodeError:
        return obj.encode('ascii', 'ignore').decode('ascii')
    except: return ""

Testen:

if __name__ == '__main__': 
    print safeStr( 1 ) 
    print safeStr( "test" ) 
    print u'98\xb0'
    print safeStr( u'98\xb0' )

Ergebnisse:

1
test
98°
98

Vorschlag: Vielleicht möchten Sie diese Funktion toAsciistattdessen benennen ? Das ist eine Frage der Präferenz.

Dies wurde für Python 2 geschrieben. Für Python 3 möchten Sie wahrscheinlich bytes(obj,"ascii")eher als verwenden str(obj). Ich habe das noch nicht getestet, aber ich werde es irgendwann tun und die Antwort überarbeiten.

BuvinJ
quelle
8

Ich habe immer den folgenden Code in die ersten beiden Zeilen der Python-Dateien eingefügt:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
Pereira
quelle
6

Einfache Hilfsfunktionen finden Sie hier .

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')
Parag Tyagi
quelle
Um den maskierten Bytestring zu erhalten (um eine beliebige Unicode-Zeichenfolge mithilfe der ASCII-Codierung in Bytes zu konvertieren), können Sie den backslashreplaceFehlerhandler verwenden : u'\xa0'.encode('ascii', 'backslashreplace'). Obwohl Sie eine solche Darstellung vermeiden und Ihre Umgebung so konfigurieren sollten, dass stattdessen Nicht-ASCII-Zeichen akzeptiert werden - es ist 2016!
JFS
Frohes Neues Jahr @JFSebastian. Ich war gerade frustriert über das Python-Unicode-Problem und bekam dann endlich diese Lösung, die funktionierte. Ich wusste nichts davon. Trotzdem danke für den Tipp.
Parag Tyagi
6

Fügen Sie einfach eine Variablencodierung hinzu ('utf-8')

agent_contact.encode('utf-8')
Kairat Koibagarov
quelle
4

Bitte öffnen Sie das Terminal und lösen Sie den folgenden Befehl aus:

export LC_ALL="en_US.UTF-8"
Hồ Ngọc Vượng
quelle
3

Ich habe gerade folgendes benutzt:

import unicodedata
message = unicodedata.normalize("NFKD", message)

Überprüfen Sie, was die Dokumentation dazu aussagt:

unicodedata.normalize (form, unistr) Gibt das normale Formular für die Unicode-Zeichenfolge unistr zurück. Gültige Werte für das Formular sind 'NFC', 'NFKC', 'NFD' und 'NFKD'.

Der Unicode-Standard definiert verschiedene Normalisierungsformen einer Unicode-Zeichenfolge, basierend auf der Definition der kanonischen Äquivalenz und der Kompatibilitätsäquivalenz. In Unicode können mehrere Zeichen auf verschiedene Arten ausgedrückt werden. Beispielsweise kann das Zeichen U + 00C7 (LATEINISCHER GROSSBUCHSTABE C MIT CEDILLA) auch als die Sequenz U + 0043 (LATEINISCHER GROSSBUCHSTABE C) U + 0327 (KOMBINIERENDE CEDILLA) ausgedrückt werden.

Für jedes Zeichen gibt es zwei Normalformen: Normalform C und Normalform D. Die Normalform D (NFD) wird auch als kanonische Zerlegung bezeichnet und übersetzt jedes Zeichen in seine zerlegte Form. Die Normalform C (NFC) wendet zuerst eine kanonische Zerlegung an und setzt dann wieder vorkombinierte Zeichen zusammen.

Zusätzlich zu diesen beiden Formen gibt es zwei zusätzliche Normalformen, die auf der Kompatibilitätsäquivalenz basieren. In Unicode werden bestimmte Zeichen unterstützt, die normalerweise mit anderen Zeichen vereinheitlicht werden. Zum Beispiel ist U + 2160 (ROMAN NUMERAL ONE) wirklich dasselbe wie U + 0049 (LATIN CAPITAL LETTER I). Es wird jedoch in Unicode aus Gründen der Kompatibilität mit vorhandenen Zeichensätzen (z. B. gb2312) unterstützt.

Die Normalform KD (NFKD) wendet die Kompatibilitätszerlegung an, dh ersetzt alle Kompatibilitätszeichen durch ihre Entsprechungen. Die Normalform KC (NFKC) wendet zuerst die Kompatibilitätszerlegung an, gefolgt von der kanonischen Zusammensetzung.

Selbst wenn zwei Unicode-Zeichenfolgen normalisiert sind und für einen menschlichen Leser gleich aussehen, sind sie möglicherweise nicht gleich, wenn einer Zeichen kombiniert und der andere nicht.

Löst es für mich. Simpel und einfach.

Drag0
quelle
3

Die folgende Lösung hat bei mir funktioniert, habe gerade hinzugefügt

u "String"

(stellt die Zeichenfolge als Unicode dar) vor meiner Zeichenfolge.

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)
Aravind Krishnakumar
quelle
3

Leider funktioniert dies zumindest in Python 3 ...

Python 3

Manchmal liegt der Fehler in den Umgebungsvariablen und ist damit verbunden

import os
import locale
os.environ["PYTHONIOENCODING"] = "utf-8"
myLocale=locale.setlocale(category=locale.LC_ALL, locale="en_GB.UTF-8")
... 
print(myText.encode('utf-8', errors='ignore'))

wobei Fehler bei der Codierung ignoriert werden.

hhh
quelle
2

Ich hatte gerade dieses Problem und Google hat mich hierher geführt. Um die allgemeinen Lösungen hier zu ergänzen, hat dies für mich funktioniert:

# 'value' contains the problematic data
unic = u''
unic += value
value = unic

Ich hatte diese Idee, nachdem ich Neds Präsentation gelesen hatte .

Ich behaupte jedoch nicht vollständig zu verstehen, warum dies funktioniert. Wenn also jemand diese Antwort bearbeiten oder einen Kommentar zur Erklärung abgeben kann, werde ich es begrüßen.

pepoluan
quelle
3
Was ist der typeWert? davor und danach? Ich denke, warum das funktioniert, ist, dass durch Ausführen eines unic += value, das dasselbe ist, wie unic = unic + valueSie einen String und einen Unicode hinzufügen, wobei Python dann Unicode für das Ergebnis annimmt, unicdh den genaueren Typ (denken Sie darüber nach, wenn Sie dies tun a = float(1) + int(1), awird ein Float) und dann value = unicverweist valueauf das neue unicObjekt , das Unicode sein geschieht.
Tom Myddeltyn
2

Wir haben diesen Fehler beim Laufen festgestellt manage.py migrate in Django mit lokalisierten Geräten gespielt haben.

Unsere Quelle enthielt die # -*- coding: utf-8 -*-Deklaration, MySQL war korrekt für utf8 konfiguriert und Ubuntu hatte das entsprechende Sprachpaket und die entsprechenden Werte/etc/default/locale .

Das Problem war einfach, dass dem Django-Container (wir verwenden Docker) das fehlte LANG env var .

Einstellung LANGzu en_US.UTF-8und Neustarten des Behälters vor dem Wieder laufenden Migrationen das Problem behoben.

followben
quelle
1

Viele Antworten hier (z. B. @agf und @Andbdrew) haben bereits die unmittelbarsten Aspekte der OP-Frage angesprochen.

Ich denke jedoch, dass es einen subtilen, aber wichtigen Aspekt gibt, der weitgehend ignoriert wurde und der für alle, die mich mögen, von großer Bedeutung ist, wenn sie versuchen, Codierungen in Python zu verstehen: Die Verwaltung der Zeichendarstellung in Python 2 und Python 3 ist völlig anders . Ich habe das Gefühl, dass ein großer Teil der Verwirrung damit zu tun hat, dass Leute über Codierungen in Python lesen, ohne sich der Version bewusst zu sein.

Ich empfehle jedem, der daran interessiert ist, die Grundursache des OP-Problems zu verstehen, zunächst Spolskys Einführung in Zeichendarstellungen und Unicode zu lesen und dann in Python 2 und Python 3 zu Batchelder auf Unicode zu wechseln .

Simón Ramírez Amaya
quelle
Ja, mein Fehler war in Python 2.7, 'a'.format (u'ñ'), und die richtige Lösung besteht darin, nicht .encode ('utf-8') zu verwenden, sondern immer Unicode-Zeichenfolgen zu verwenden (die Standardeinstellung in Python 3) ): u'a'.format (u'ñ '),
Rogelio
1

Vermeiden Sie die Konvertierung der Variablen in str (Variable). Manchmal kann es das Problem verursachen.

Einfacher Tipp zu vermeiden:

try: 
    data=str(data)
except:
    data = data #Don't convert to String

Das obige Beispiel löst auch den Encode-Fehler.

Sam Ruben
quelle
Dies funktioniert nicht, da Sie nur auf den Fehler in der Ausnahme
Aurele Collinet
0

Wenn Sie so etwas haben, packet_data = "This is data"tun Sie dies in der nächsten Zeile direkt nach der Initialisierung packet_data:

unic = u''
packet_data = unic
Nandan Kulkarni
quelle
0

Ich hatte dieses Problem beim Versuch, Unicode-Zeichen auszugeben stdout, aber mitsys.stdout.write anstatt zu drucken auszugeben (damit ich auch die Ausgabe in eine andere Datei unterstützen konnte).

Aus der eigenen Dokumentation von BeautifulSoup habe ich dies mit der Codecs-Bibliothek gelöst:

import sys
import codecs

def main(fIn, fOut):
    soup = BeautifulSoup(fIn)
    # Do processing, with data including non-ASCII characters
    fOut.write(unicode(soup))

if __name__ == '__main__':
    with (sys.stdin) as fIn: # Don't think we need codecs.getreader here
        with codecs.getwriter('utf-8')(sys.stdout) as fOut:
            main(fIn, fOut)
palswim
quelle
0

Dieses Problem tritt häufig auf, wenn ein Django-Projekt mit Apache bereitgestellt wird. Weil Apache die Umgebungsvariable LANG = C in / etc / sysconfig / httpd setzt. Öffnen Sie einfach die Datei und kommentieren Sie diese Einstellung (oder ändern Sie sie in Ihren Geschmack). Oder verwenden Sie die Option lang des Befehls WSGIDaemonProcess. In diesem Fall können Sie verschiedene LANG-Umgebungsvariablen für verschiedene virtuelle Hosts festlegen.

shmakovpn
quelle
0

Die empfohlene Lösung hat bei mir nicht funktioniert, und ich könnte damit leben, alle Nicht-ASCII-Zeichen zu löschen

s = s.encode('ascii',errors='ignore')

was mich mit etwas gestrippt hat, das keine Fehler wirft.

Gulzar
quelle
0

Das wird funktionieren:

 >>>print(unicodedata.normalize('NFD', re.sub("[\(\[].*?[\)\]]", "", "bats\xc3\xa0")).encode('ascii', 'ignore'))

Ausgabe:

>>>bats
Huzefa Usama
quelle