UnicodeDecodeError:

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
minetestmob
User
Beiträge: 2
Registriert: Sonntag 3. Mai 2020, 17:00

Hallo,

beim Auslesen von Dateien, die ich zugeschickt bekomme, erhalte ich manchmal einen Kodierungsfehler:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe4 in position 28: invalid continuation byte

Ich verwende Python3 und habe die Zeile

Code: Alles auswählen

# -*- coding: utf-8 -*-
nicht vergessen. :-)

Code: Alles auswählen

p = open(Datei)
text = p.read()
Die Dateien liegen komplett in UTF-8 vor bis auf ein einzelnes "kaputtes" Zeichen. Im Editor bekomme ich hier zum Beispiel ein "ä" angezeigt. Überschreibe ich es mit einem ä, dann läuft das Python-Programm problemlos durch. Mein Editor hat aus dem kaputten ein ganzes ä in UTF-8 gemacht. Das würde ich gerne von Python automatisch erledigen lassen, d.h. wenn ich beim Lesen ein 0xe4 finde, soll einfach ein ä angezeigt werden ohne die Originaldatei zu ändern.

Hat jemand eine Idee, wie das funktioniert?

Gruß,
Chris
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@minetestmob: Der Kodierungskommentar gibt die Kodierung von der Python-Quelltextdatei an in der er steht und muss mit der tatsächlichen Kodierung dieser Datei übereinstimmen. Das hat nichts mit irgendwelchen anderen Dateien zu tun.

Beim öffnen von Textdateien sollte man immer explizit die Kodierung angeben. Sonst ”rät” Python die Systemkodierung und die kann auf jedem System anders sein. Wenn Dein Programm also immer UTF-8 kodierte Textdateien erwartet, sollte genau das bei `open()` angegeben werden.

Wenn ein Bytewert 0xe4 in den Daten für ein "ä" steht, dann ist die Datei offensichtlich nicht UTF-8 kodiert. Das lässt sich nicht magisch irgendwie ändern. Entweder müssen die Dateien UTF-8 kodiert sein, oder Du musst die Kodierung in der die Datei tatsächlich vorliegen, beim öffnen der Datei angeben. Man kann versuchen die richtige Kodierung zu raten, aber das geht nicht 100%ig.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
minetestmob
User
Beiträge: 2
Registriert: Sonntag 3. Mai 2020, 17:00

Der Kodierungskommentar gibt die Kodierung von der Python-Quelltextdatei an
War schon klar, aber ich habe die ähnlichen Threads zum Thema gelesen und wollte dieser Antwort zuvorkommen.
Wenn ein Bytewert 0xe4 in den Daten für ein "ä" steht, dann ist die Datei offensichtlich nicht UTF-8 kodiert.
Das war das Problem, das ich beschrieb:
Die Dateien liegen komplett in UTF-8 vor bis auf ein einzelnes "kaputtes" Zeichen.
Entweder müssen die Dateien UTF-8 kodiert sein, oder Du musst die Kodierung in der die Datei tatsächlich vorliegen
Weil das so ist, was aus meine Frage doch hervorgegangen sein sollte, fragte ich nach einer Lösung des Problems. Natürlich könnte ich nun, bevor ich mein Python-Skript ausführe, mit einem Shellskript oder einer anderen Programmiersprache den Text vorbearbeiten, so das Python damit klar kommt, aber das ist zum einen umständlich und zum anderen könnte ich dann auch gleich die andere Sprache nehmen. Eleganter wäre es doch, wenn ich den UnicodeDecodeError abfange, das Nicht-UTF-Zeichen ersetze und das Programm weiterlaufen lasse.

Was mir vorschwebt ist sowas

Code: Alles auswählen

p = open(Datei, mode="r", encoding="utf-8") # ;-)
try:
	text = p.read()
except UnicodeDecodeError:
	if kaputtes_Zeichen = Bytewert 0xe4:
		kaputtes_Zeichen = ä     # (oder nichts, wenn ich nicht weiß, was das sein soll)
		kaputtes_Zeichen.encode('utf-8')    # dürfte hier nicht funktionieren
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Man kann beim dekodieren angeben, wie man mit solchen Faellen umgehen will: https://docs.python.org/3/howto/unicode ... tring-type
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn Du eine Vorverarbeitung auf Byte-Level machen möchtest, dann mußt Du die Datei binär laden, die Ersetzung b"\xe4" -> b'\xc3\xa4' machen und dann erst decodieren. Dabei mußt Du natürlich aufpassen, dass Du durch Deine Ersetzung nicht irgendwelche anderen Unicode-Zeichen kaputt machst.
Antworten