Strings fluchten

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.
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

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
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

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] == '\'
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

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
Diese Nachricht zersört sich in 5 Sekunden selbst ...
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

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?
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

http://www.python-forum.de/topic-13229.html

Edit: Ich hab bei fluchten auch an ausrichten (im Sinne von align) gedacht.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

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.
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

Rebecca hat geschrieben:http://www.python-forum.de/topic-13229.html

Edit: Ich hab bei fluchten auch an ausrichten (im Sinne von align) gedacht.
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
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

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.

Code: Alles auswählen

"Hail Eris!\nAll Hail Discordia!".encode("base64")
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.
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

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
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

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.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

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.
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

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 ;)
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

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
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

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. :-D

Danke für eure Hilfe!!

Gruß,
Michel
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

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")
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

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
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

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.
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

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
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

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', '\\' : '\\'})
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

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
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Antworten