Seite 1 von 2
Strings fluchten
Verfasst: Donnerstag 31. Januar 2008, 10:17
von Michael Schneider
Hallo,
ich habe mal wieder ein Problem und bin zu blind, Pythons build-in Lösung zu finden.
gegeben: ein String mit line-feed, tabs, etc.
gesucht: derselbe String, wobei die Sonderzeichen einmal gefluchtet wurden
Beispiel:
vorher -> "Hello\tWorld" mit \t = 1 Tab-Zeichen
nachher -> "Hello\\tWorld", wobei aus Tab ein gefluchteter Backslash und ein t wurden
Wie aus dem Beispiel zu erkennen, müssen backslashs ebenfalls gefluchtet werden.
Ich habe mir eine Lösung selbst programmiert, aber ich wüsste gern eine Python-Funktion, die das für mich übernimmt. So wie escape_string() von MySQLdb. Aber da es diese Methode gibt, gehe ich mal davon aus, dass Python sowas nicht in den Bordmitteln hat, oder?
Kann mir jemand helfen?
Vielen Dank, Gruß
Michel
Re: Strings fluchten
Verfasst: Donnerstag 31. Januar 2008, 10:41
von keppla
Das erste mal, dass ich das wort "gefluchtet" höre
gegeben: ein String mit line-feed, tabs, etc.
gesucht: derselbe String, wobei die Sonderzeichen einmal gefluchtet wurden
Die Frage ist, nach welcher Logik? Wer soll den String danach einlesen? "\x00" mag ein gültiger String in python sein, in mysql vmtl nicht.
Für python kannst du strings mit "repr" escapen:
Code: Alles auswählen
x = "\x00"
esaped = repr(x)
assert len(escaped) == 6
assert escaped[1] == '\'
Re: Strings fluchten
Verfasst: Donnerstag 31. Januar 2008, 10:49
von Michael Schneider
keppla hat geschrieben:Das erste mal, dass ich das wort "gefluchtet" höre

Wirklich? Ich habe das schon oft gelesen.
keppla hat geschrieben:
Die Frage ist, nach welcher Logik? Wer soll den String danach einlesen? "\x00" mag ein gültiger String in python sein, in mysql vmtl nicht.
Stimmt. Also es soll für Python gefluchtet sein. Das heißt, dass definitiv kein lf oder tab oder cr im String mehr vorkommt, sondern durch die 'echten' Zeichen ersetzt wird, die man auch auf dem Bildschirm lesen kann. (Ausnahme ist der Backslash)
Ich möchte die Daten vornehmlich übers Netz schicken und lf als terminator verwenden. Der String "\x00" würde ja als ein Zeichen (lf) im hexadezimalformat interpretiert werden, was letztlich dieselbe Wirkung hat.
keppla hat geschrieben:Für python kannst du strings mit "repr" escapen:
kopfschüttel
Man, das ist so einfach und doch so genial!
Aber: wie bekomme ich daraus wieder sicher den Originalstring? Ich meine, wenn ich eval verwende, dann kann dabei ja auch alles andere passieren. Gibt es eine Möglichkeit, den repr-String wieder direkt in den Originalstring umzuwandeln?
Vielen Dank!
Gruß,
Michel
Verfasst: Donnerstag 31. Januar 2008, 11:11
von rayo
Hi
Wäre es nicht einfacher bei der Übertragung übers Netzwerk zuerst die Grösse und dann die Daten zu übertragen?
<4byte Grösse><daten>
Dann weiss der Empfänger wieviele Daten er empfangen muss und braucht nicht auf einen Terminator zu warten, somit musst du auch nichts escapen.
Gruss
PS: Das Wort fluchten war mir bis jetzt auch unbekannt
*edit* Aber irgendwie passt das auch nicht, bei dict.leo.org gibt fluchten ja aligning und bei
Wiki steht 'etwas in eine (gerade) Linie bringen', '(sich) ausrichten'. Den String musst du ja nicht ausrichten oder?
Verfasst: Donnerstag 31. Januar 2008, 11:20
von Rebecca
http://www.python-forum.de/topic-13229.html
Edit: Ich hab bei fluchten auch an ausrichten (im Sinne von align) gedacht.
Verfasst: Donnerstag 31. Januar 2008, 11:25
von Michael Schneider
rayo hat geschrieben:Hi
Wäre es nicht einfacher bei der Übertragung übers Netzwerk zuerst die Grösse und dann die Daten zu übertragen?
<4byte Grösse><daten>
Hi Rayo,
es gibt generell zwei Möglichkeiten der Übertragung. Wenn die Größe bekannt ist, dann ist es zweckmäßig die Größe anzugeben und dann n Zeichen zu lesen. Insbesondere in Hinblick auf eine Fortschrittsauswertung.
Es gibt aber auch Umstände, da möchte man einen Stream lesen, der jederzeit unterbrochen werden kann. Beispiel: eine x Mb Datei, die, solange sich kein wichtigeres Paket dazwischendrängt (z.B. eine Chatzeile), gleichmäßig übertragen werden kann. Würde man die in Häppchen zerteilen, hätte man entweder Verzögerungen bei der Übertragung der wichtigen Pakete (große Chunks) oder mehr Overhead und Verarbeitungsaufwand (kleine Chunks).
rayo hat geschrieben:Dann weiss der Empfänger wieviele Daten er empfangen muss und braucht nicht auf einen Terminator zu warten, somit musst du auch nichts escapen.
Ich wollte auch eigentlich kein direktes Beispiel angeben, damit die Diskussion nicht von der eigentlichen Frage abdriftet, denn es geht um das generelle Problem. (ich möchte auch binäre Strings pickeln (mit einem alten Pickle-modul), wobei ich nur die Sonderzeichen fluchten will)
Gruß,
Michel
p.s. Ich kann mich mit dem neudeutschen "escapen" nicht wirklich anfreunden.
Verfasst: Donnerstag 31. Januar 2008, 11:35
von Michael Schneider
Hi Rebecca,
ich habe auch schon an encode/decode gedacht, aber ich habe keinen Codec namens "string-escape". Dafür bekomme ich einen
ExceptHook hat geschrieben:LookupError: unknown encoding: string-escape
Kann ich den irgendwo herbekommen?
Gruß,
Michael
Re: Strings fluchten
Verfasst: Donnerstag 31. Januar 2008, 12:08
von keppla
Ich möchte die Daten vornehmlich übers Netz schicken und lf als terminator verwenden.
würde sich da nicht sowas wie base64 anbieten? Hat mit absoluter Sicherheit nur einen wohldefinierten Zeichensatz.
Wenn du dir ein Netzwerkprotokoll ausdenkst, hängt es imho sehr davon ab, was du erreichen möchtest.
Ich fand längenpräfixe eigentlich immer eine recht angenehme lösung, wenn man beliebig lange elemente haben möchte, macht man es halt wie http-chunked: man liest solange chunks ein, bis ein leeres kommt.
Re: Strings fluchten
Verfasst: Donnerstag 31. Januar 2008, 12:34
von Michael Schneider
keppla hat geschrieben:Ich möchte die Daten vornehmlich übers Netz schicken und lf als terminator verwenden.
würde sich da nicht sowas wie base64 anbieten? Hat mit absoluter Sicherheit nur einen wohldefinierten Zeichensatz.
Um nochmal auf base64 einzugehen: das macht aus 3 Zeichen 4, was den Text um 25% verlängert, während eine hand voll Sonderzeichen vielleicht 4-5% ausmacht. Außerdem hatte ich damit Probleme mit Umlauten wie ä, ö, ü, weil der base64-codec immer über das ascii-Format lief, welches bestimmt chars (>= Wert 128) nicht übersetzen konnte. Darum hatte ich den base64-Ansatz zurückgestellt.
keppla hat geschrieben:
Wenn du dir ein Netzwerkprotokoll ausdenkst, hängt es imho sehr davon ab, was du erreichen möchtest.
Ich fand längenpräfixe eigentlich immer eine recht angenehme lösung, ...
Ich möchte wirklich nicht unhöflich klingen. Aber es geht hier nicht um alternative Netzwerkprotokolle, sondern um die Frage wie man vorhandene Strings per Funktion fluchten/escapen und das Ergebnis wieder in den Originalstring umwandeln kann (siehe Originalmail). Wie gesagt betrachte ich das als Grundsatzproblem und suche keine gute Möglichkeit, das Fluchten zu umgehen. Das sollte jetzt nicht undankbar wirken!
Übrigens heißt der Backslash auf deutsch doch Fluchtungszeichen. Warum dann die Aktion nicht fluchten?
Grüße,
Michael
Re: Strings fluchten
Verfasst: Donnerstag 31. Januar 2008, 13:18
von keppla
Ich möchte wirklich nicht unhöflich klingen. Aber es geht hier nicht um alternative Netzwerkprotokolle, sondern um die Frage wie man vorhandene Strings per Funktion fluchten/escapen und das Ergebnis wieder in den Originalstring umwandeln kann (siehe Originalmail).
ist schon klar, allerdings ist es wohl ebenfalls nicht unhöflich, zu versuchen zu ermitteln, ob das vorgetragene Problem das eigentliche Problem ist.
Übrigens heißt der Backslash auf deutsch doch Fluchtungszeichen. Warum dann die Aktion nicht fluchten?
Sagte ich ja nicht, ich sagte nur, dass ich diese (eindeutschung?) heute das erste mal höre.
Ich habe gerade mal
in der doku nachgelesen, string_escape bzw unicode_escape scheinen das zu sein, was du suchst.
Verfasst: Donnerstag 31. Januar 2008, 13:21
von Y0Gi
Wird da etwa "to escape" mit "fluchten" übersetzt? Holla ...
Michael, ich hoffe, du liest nicht mehr dort, wo du das zuerst gelesen hast
"Maskieren" ist der mir sehr geläufige deutsche Ausdruck dafür.
Verfasst: Donnerstag 31. Januar 2008, 13:25
von keppla
Y0Gi hat geschrieben:Wird da etwa "to escape" mit "fluchten" übersetzt? Holla ...
Michael, ich hoffe, du liest nicht mehr dort, wo du das zuerst gelesen hast

Stellt sich die Frage, was für Stilblüten da bei "callback function" oder "message handler" rauskommen

Verfasst: Donnerstag 31. Januar 2008, 13:29
von Rebecca
Wikipedia, Leo und ich kennen den Backslash im Deutschen als umgekehrten Schrägstrich oder linksseitigen Schrägstrich.
Soweit ich weiss, gehoert der string-escape-Codec standardmaessig dazu, ich hab ihn unter Debian jedenfalls hier:
python2.4-minimal: usr/lib/python2.4/encodings/string_escape.py
python2.5-minimal: usr/lib/python2.5/encodings/string_escape.py
Verfasst: Donnerstag 31. Januar 2008, 13:48
von Michael Schneider
Unter Python2.2 habe ich nur:
raw_unicode_escape.py
unicode_escape.py
Damit wird das Ergebnis zwar beim Dekodieren in einen Unicode-String umgewandelt, aber mit str bekomme ich das Original wieder.
re: Fluchten
Ok, ich gebe mich geschlagen - schaut doch mal bei Google unter dem Begriff
"strings fluchten"
... ich bin Trendsetter - nur hoffentlich greift das keiner auf.
Danke für eure Hilfe!!
Gruß,
Michel
Verfasst: Donnerstag 31. Januar 2008, 14:04
von keppla
Michael Schneider hat geschrieben:Unter Python2.2 habe ich nur:
raw_unicode_escape.py
unicode_escape.py
Damit wird das Ergebnis zwar beim Dekodieren in einen Unicode-String umgewandelt, aber mit str bekomme ich das Original wieder.
musst das ganze auch decodieren:
Code: Alles auswählen
x = "Hail Eris!\nAll Hail Discordia!"
assert x == x.encode("string_escape").decode("string_escape")
Verfasst: Donnerstag 31. Januar 2008, 14:15
von Michael Schneider
keppla hat geschrieben:Michael Schneider hat geschrieben:Unter Python2.2 habe ich nur:
raw_unicode_escape.py
unicode_escape.py
Damit wird das Ergebnis zwar beim Dekodieren in einen Unicode-String umgewandelt, aber mit str bekomme ich das Original wieder.
musst das ganze auch decodieren:
Code: Alles auswählen
x = "Hail Eris!\nAll Hail Discordia!"
assert x == x.encode("string_escape").decode("string_escape")
Hi Keppla,
was meinst Du damit?
Erstens habe ich kein "string_escape" codec (habe bei dem obigen Suchergebnis nach allen Dateien gesucht, die "escape" enthalten).
Zweitens bringt es mir nichts, den String zu codieren und gleich wieder zu dekodieren. Ich muss ihn doch zwischendurch noch senden/bearbeiten/speihern, oder? Ich habe Dich bestimmt falsch verstanden.
Michael
Verfasst: Donnerstag 31. Januar 2008, 16:51
von keppla
Sorry, vergiss mein Post, ich hatte das "Python 2.2" völlig übersehen, und dich irgendwie ganz anders verstanden. Bin scheinbar nicht gerade auf der höhe.
Erstens habe ich kein "string_escape" codec (habe bei dem obigen Suchergebnis nach allen Dateien gesucht, die "escape" enthalten).
Hatte ich übersehen.
Zweitens bringt es mir nichts, den String zu codieren und gleich wieder zu dekodieren.
Damit wollte ich die symmetrie der zwei funktionen verdeutlichen, in der Fehlannahme, dass du das mit irgendwelchen scripts lösen wolltest. Wie gesagt, is heut nicht mein tag.
Also, mal etwas produktiver:
mit codec.register kann man sich "eigene" codecs registrieren. Eine mögliche lösung wäre, wenn der "string_encode" in python geschrieben ist, diesen teil aus python2.5 zu kopieren (unter Beachtung der Lizenz versteht sich), ihn zu registrieren, und mitzuverteilen.
Verfasst: Donnerstag 31. Januar 2008, 22:53
von Michael Schneider
keppla hat geschrieben:
Also, mal etwas produktiver:
mit codec.register kann man sich "eigene" codecs registrieren. Eine mögliche lösung wäre, wenn der "string_encode" in python geschrieben ist, diesen teil aus python2.5 zu kopieren (unter Beachtung der Lizenz versteht sich), ihn zu registrieren, und mitzuverteilen.
Hi Keppla,
daran habe ich auch schon gedacht und wollte fragen, ob mir jemand dieses string-codec Modul posten kann. Aber wie es aussieht, sind die wrapper.py Dateien mit "escape" im Namen (oben) nur Wrapper für C-Funktionen. Daher denke ich, dass das auch für den string_escape codec gilt.
Aber mit dem unicode_escape fahre ich ja ganz gut, das ist vielleicht sogar noch etwas sicherer, was Umlaute betrifft.
Gruß,
Michael
Verfasst: Freitag 1. Februar 2008, 11:19
von keppla
Michael Schneider hat geschrieben:Aber mit dem unicode_escape fahre ich ja ganz gut, das ist vielleicht sogar noch etwas sicherer, was Umlaute betrifft.
Wenn ich dein vorhaben richtig verstehe, dürften die doch keine probleme machen können.
Ob umlaute richtig verstanden werden ist ja eher eine frage, ob sender und empfänger sich auf ein encoding geeinigt haben (was bei dir ja zwangsläufig ist, da du beide Programmierst).
Wenn ich dein Protokoll richtig verstehe, möchtest du "token" senden, trennzeichen wäre \n.
Womit klar wäre: \n ist dein einziges steuerzeichen, du musst also nur dieses escapen.
So einen codec selbst zu schreiben ist imho nicht so schwer.
edit: um mal meinen Worten taten folgen zu lassen:
Code: Alles auswählen
def decode(s, escape, trans):
chunks = []
left = 0
while True:
right = s.find(escape, left)
if right == -1:
chunks.append(s[left:])
break
else:
chunk = s[left:right] + trans[s[right + 1]]
chunks.append(chunk)
left = right + 2
return ''.join(chunks)
message = r"Hail Eris!\nAll Hail Discordia!\n\\ <- this is a backslash"
print message
print decode(message, '\\', {'n' : '\n', '\\' : '\\'})
Verfasst: Freitag 1. Februar 2008, 12:37
von Michael Schneider
keppla hat geschrieben:So einen codec selbst zu schreiben ist imho nicht so schwer.
Hi,
wie ich eingangs schrieb, habe ich das auch selbst schon implementiert. Aber dabei kam ich auf meine grundsätzliche escape/unescape Frage.
Schönes Wochenende,
Michel