Seite 1 von 2

Ausfürliche Definition der pickle Protokolle

Verfasst: Montag 20. Juli 2009, 22:34
von mabe
Hi Phyton Leutz,

ich möchte das/die "pickle"-Protokoll(e) von Phyton gerne mit PHP nutzen können, damit man z.B: zwischen den beiden Programmiersprachen besser kommunizieren kann. Nur leider finde ich nirgends eine ausführliche Definition der Protokolle :(

Das einzige was ich neben der API gefunden habe ist das hier:
http://pickle-js.googlecode.com
ist aber halt nicht komplett.

Könnt Ihr mir da weiterhelfen ?

Verfasst: Montag 20. Juli 2009, 22:39
von cofi
Der Quelltext von ``pickle`` sollte helfen ;)

Aber bei deinem Problem bietet sich eigentlich eher JSON an. Dafuer sollte es eigentlich auch PHP Libs geben. Auch wenn ich nicht verstehe warum man PHP nutzen sollte, wenn man Python haben kann...

Verfasst: Montag 20. Juli 2009, 22:56
von mabe
Auch wenn ich nicht verstehe warum man PHP nutzen sollte, wenn man Python haben kann...
*G* Genau darauf habe ich gewartet, aber egal
Aber bei deinem Problem bietet sich eigentlich eher JSON an. Dafuer sollte es eigentlich auch PHP Libs geben.
Ja klar gibt es, aber nicht alle Datentypen werden dann sauber übersetzt und zudem verliert man auch noch alle Referenzen, was sich bei größeren Datenmengen schon bemerkbar macht.

Verfasst: Montag 20. Juli 2009, 23:20
von DatenMetzgerX
Du kannst eigene serialisierer / deserialisierer programmieren, dann können die "referenzen" ( die eh by Value sind) nicht verloren.

Verfasst: Dienstag 21. Juli 2009, 11:12
von Defnull
Nimm Json. Für beide Sprachen gibt es da Packete für.

Verfasst: Dienstag 21. Juli 2009, 11:15
von lunar
Defnull hat geschrieben:Nimm Json. Für beide Sprachen gibt es da Packete für.
Das wurde schon erwähnt ... und es wurde auch schon gesagt, warum das für den OP nicht unbedingt sinnvoll ist.

Verfasst: Dienstag 21. Juli 2009, 11:17
von Defnull
Sorry, es ist ja noch früh *hust*

Verfasst: Dienstag 21. Juli 2009, 11:33
von ms4py
Im Paket gnosis gibt das Modul xml.pickle
http://pypi.python.org/pypi/Gnosis%20Utilities/1.2.1

Wird z.B. von Pyro als Alternative zu pickle verwendet. Vielleicht wär das ja was für dich, wenn man das erzeugte XML in PHP einfach parsen kann.

Verfasst: Dienstag 21. Juli 2009, 13:00
von Leonidas
Oder man koennte die Pickle-Stacksprache in PHP implementieren. Wobei ich mir nicht sicher bin, ob mitsuhiko nicht genau das schon früher mal gemacht hat.

Verfasst: Dienstag 21. Juli 2009, 16:39
von Hyperion
Wo genau liegt das Problem mit Referenzen? Kannst Du da mal ein Beispiel geben? Würde mich mal interessieren, wie man das ggf. in JSON doch handeln kann.

Alleine die Größe kann's ja nicht sein, denn man sollte JSON gut zippen können.

Verfasst: Dienstag 21. Juli 2009, 17:45
von birkenfeld
Defnull hat geschrieben:Nimm Json. Für beide Sprachen gibt es da Packete für.
Pakete, bitte.

Und @OP: wenn du dir zutraust, pickle in PHP zu implementieren, solltest du dir auch zutrauen, die Protokolldefinition aus pickle.py zu holen :)

Verfasst: Dienstag 21. Juli 2009, 18:41
von lunar
Hyperion hat geschrieben:Wo genau liegt das Problem mit Referenzen? Kannst Du da mal ein Beispiel geben?
Jede zyklische Datenstruktur kann man nicht einfach so serialisieren. Das betrifft beispielsweise doppelt verkettete Listen oder Bäume der Art Vater->Kinder, Kind->Vater. Da jedes Element auch wieder eine Referenz auf seinen Vorgänger hat, kann ein "dummer" Serialisierungsversuch gar nicht terminieren.

Um solche Datenstrukturen zu serialisieren, muss man die Zyklen entweder manuell lösen (in dem man z.B. im Baum alle Referenzen auf das Vater-Element nullt) oder eben ein Serialisierungsformat entwickeln, welches Referenzen hat.

Verfasst: Dienstag 21. Juli 2009, 18:45
von BlackJack
@Hyperion: Auch Strukturen ohne Zyklen können Probleme bereiten, weil Referenzen durch das serialisieren nach JSON verloren gehen, und damit verhalten sich die Ergebnisse anders:

Code: Alles auswählen

In [3]: a = [1, 2]

In [4]: b = [a, a]

In [5]: b
Out[5]: [[1, 2], [1, 2]]

In [6]: c = pickle.loads(pickle.dumps(b))

In [7]: c
Out[7]: [[1, 2], [1, 2]]

In [8]: c[0][1] = 42

In [9]: c
Out[9]: [[1, 42], [1, 42]]

In [10]: c = simplejson.loads(simplejson.dumps(b))

In [11]: c
Out[11]: [[1, 2], [1, 2]]

In [12]: c[0][1] = 42

In [13]: c
Out[13]: [[1, 42], [1, 2]]

Verfasst: Dienstag 21. Juli 2009, 19:13
von mabe
Und @OP: wenn du dir zutraust, pickle in PHP zu implementieren, solltest du dir auch zutrauen, die Protokolldefinition aus pickle.py zu holen Smile
Wenn es keine Doku dazu gibt werde ich das wohl machen müssen. Mal gucken wie ich mich beim lesen von Python so anstelle.

-> Wenn das soweit funktioniert stell ich das hier wieder rein.

Verfasst: Dienstag 21. Juli 2009, 20:48
von Hyperion
@BlackJack & @Lunar: Danke für die Beispiele - wieder was gelernt :-)

Verfasst: Dienstag 21. Juli 2009, 22:56
von DasIch
JSON ist gar keine so dumme Idee aber knapp vorbei ist auch vorbei.

Code: Alles auswählen

>> import yaml
>> a = [1, 2]
>> b = [a, a]
>> b
 > [[1, 2], [1, 2]]
>> c = yaml.load(yaml.dump(b))
>> c
 > [[1, 2], [1, 2]]
>> c[0][1] = 42
>> c
 > [[1, 42], [1, 42]]
>> print yaml.dump(b)
- &id001 [1, 2]
- *id001

Verfasst: Mittwoch 22. Juli 2009, 09:53
von sma
Es hat ungefähr 15 Minuten gedauert, einen eigenen Serializer zu bauen, der so einfach ist, dass man sicherlich auch ein PHP-Gegenstück bauen kann und der dies kann:

Code: Alles auswählen

>>> d = {1: "zwei", 3: [True]}; d[3].append(d)
>>> Serializer().write(d)
"{(I1S'zwei';(I3[TR0;;;"
Das { steht für dict, ( für tuple, I für int und S für str. Danach kommen jeweils die Daten. Sequenzen werden mit ; beendet. Das R ist eine Referenz, damit rekursive Datenstrukturen funktionieren. Der Encoder hat 21 Zeilen, der Decoder 26.

http://gist.github.com/151889

Stefan

Verfasst: Mittwoch 22. Juli 2009, 10:12
von birkenfeld
Sieht nett aus!

Zwei Anmerkungen: Strings mit Single-Quotes und negative Integers mag das Ding nicht, und das Slicing von m.group() könnte man vermeiden, wenn man die Gruppen in der Regex auf den eigentlichen Wert einschränkt. Ach ja, und es dürfte schneller sein, den String nicht nach jedem Match zu slicen, sondern einfach einen Startindex i zu inkrementieren und ihn re.match mitzugeben (dafür braucht es aber ein regex-Objekt).

Verfasst: Mittwoch 22. Juli 2009, 10:30
von sma
Hatte nicht bedacht, dass `repr()`von ' auf " wechselt, wenn ein ' im String vorkommt. Das und negative Zahlen werden jetzt erkannt. Für Strings ist der reguläre Ausdruck allerdings immer noch zu trivial, denn er erkennt keine \. Das überlasse ich dem Leser als Übung.

Ansonsten habe ich nach birkenfelds Blick den Code nochmals geändert, weil mir doch 40 Zeilen für den Decoder einfach zu viel waren. Auf Effizienz hatte ich zwar überhaupt nicht geachtet, aber ich denke, das neue Verfahren würde besser performen, wenn einem das wichtig wäre.

Stefan

Verfasst: Mittwoch 22. Juli 2009, 10:44
von birkenfeld
LOC durch 1-Zeilen-Suiten zu sparen, ist natürlich keine Kunst :)