Escape-Sequenz in Unicode umwandeln

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
Qdeep

Hallo!

Ich möchte Daten mit escapten Umlauten aus einer Datei lesen und als UTF-8-Datei (mit den Umlauten) in eine Datei schreiben.
Die Lesedatei enthält z.B. "n\xf6rgeln" und ich möchte es in eine Datei als "nörgeln" speichern.

Jetzt verhält sich Python komisch.
Wenn ich den String direkt als

Code: Alles auswählen

s = "n\xf6rgeln"
eingebe, kann ich ihn einfach mittels

Code: Alles auswählen

s = s.decode("cp1252")
in einen Unicodestring umwandeln und damit weiterarbeiten, am Ende auch mit encode("utf8") als Unicode-Datei abspeichern.

Das Problem ist, dass wenn ich diesen Stringteil aus einer Datei lese, der String die ganze Zeit mit der Escape-Sequenz erhalten bleibt. Beim Debuggen fällt auf, dass "s" gleich "n\\xf6rgeln" ist, also dass der Backslash escapt wurde. Die Umwandlung in Unicode mittels decode bringt dann leider nichts, die Sequenz bleibt erhalten; es entsteht also nicht u"nörgeln", sondern u"n\\xf6rgeln".

Liegt das daran, dass ich aus einer Datei lese? Ich versteh das Verhalten hier nicht.


Hier mal ein bisschen mehr Code:
Datei, aus der gelesen wird:

Code: Alles auswählen

[...]
text=n\xf6rgeln
[...]
Mein Script:

Code: Alles auswählen

fobj = open("datei.txt", "r")
for line in fobj:
	line = line.strip()
	curText = line.split("=")[1]
	curText = curText.decode("cp1252")
	print curText
fobj.close()
Die Ausgabe ist leider nicht "nörgeln", sondern "n\xf6rgeln".

Bitte um Hilfe, danke :)
Qdeep
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Ist zwar ein Schuss ins Blaue, aber versuch einfach mal `codecs.open` mit utf-8 ;)
„Lieber von den Richtigen kritisiert als von den Falschen gelobt werden.“
Gerhard Kocher

http://ms4py.org/
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Ich habe das so verstanden, dass in der Textdatei die Zeichenfolge "\ x f 6" steht. Dennoch hat die Datei offensichtlich ein Encoding, entweder ISO-8859-{1,15} oder CP1252. Das musst du kennen. Dann kannst du die Datei (mit Python 3.1) wie folgt zunächst in ein bytes-Objekt laden und dann decoden, also die Bytes unter Anwendung einer Kodierung in ein String-Objekt verwandeln. In Python 2.x geht das im Prinzip genauso, nur heißt dort das bytes-Objekt (fälschlicherweise) String und der String heißt "unicode".

Code: Alles auswählen

with open("...", "rb") as f:
    b = f.read()
s = b.decode("unicode_escape")
with open("...", "w", encoding="utf-8") as f:
    f.write(s)
Liegt allerdings bereits ein String vor, der \ x f 6 als Zeichenfolge enthält, fällt mir (bei Python 3.1) kein einfacher Weg ein, das zu dekodieren, weil str diese Methode nicht kennt. Aber es gibt ja reguläre Ausdrücke:

Code: Alles auswählen

def str_unescape(s):
    return re.sub(r"\\x([a-fA-F0-9]{2})", lambda m:chr(int(m.group(1), 16)), s)
Stefan
Qdeep

Perfekter Schuss ;)

Code: Alles auswählen

import codecs
curText = codecs.escape_decode(curText)[0].decode("cp1252")
führt hier zum Ziel!
escape_decode bewirkt, dass die Escape-Sequenz dekodiert wird und nun ein sauberer String vorliegt. decode(Codepage) macht daraus dann eine Unicode-Instanz, die mit encode("utf8") dann als UTF-8-Datei abgespeichert werden kann.

Wunderbar, danke für die schnelle Hilfe!
Qdeep
Antworten