2010-06-14 6 views
6

Tengo que deserializar un diccionario en PHP que fue serializado usando cPickle en Python.Python's cPickle deserialization from PHP?

En este caso específico, probablemente podría simplemente regexp la información deseada, pero ¿hay una manera mejor? ¿Alguna extensión para PHP que me permita deserializar de forma más nativa todo el diccionario?

Al parecer, es de serie en Python como esto:

import cPickle as pickle 

data = { 'user_id' : 5 } 
pickled = pickle.dumps(data) 
print pickled 

contenido de tales serialización no se pueden pegar fácilmente a aquí, ya que contiene datos binarios.


Solución

Desde finales de Python es Django, terminé creando own JSON SessionStore.

+3

Mencionó que la serialización no está bajo su control. ¿Cómo está recibiendo estos datos en escabeche? Un archivo local? –

+0

Viene de la base de datos en Django, es session_data en la tabla de sesiones django. Probablemente termine escribiendo SessionMiddleware para serializar session_data como JSON. Solo deseé no tener que modificar la aplicación Django para esto. – Ciantic

Respuesta

7

Si desea compartir objetos de datos entre programas escritos en diferentes idiomas, podría ser más fácil serializar/deserializar usando algo como JSON en su lugar. La mayoría de los principales lenguajes de programación tienen una biblioteca JSON.

+2

Python 2.6+ tiene incorporado, y hay simplicjson para versiones anteriores. –

+2

Aunque es una buena idea, la parte de serialización no está bajo mi control. – Ciantic

+0

Al principio pensé que no quería hackear la aplicación Django, pero de nuevo podría ser una solución más rápida. Así que aquí está mi sencilla [JSON SessionStore for Django] (http://gist.github.com/441132) – Ciantic

5

¿Puede hacer una llamada al sistema? Se puede usar un script en Python como este para convertir los datos de la salmuera en JSON:

# pickle2json.py 
import sys, optparse, cPickle, os 
try: 
    import json 
except: 
    import simplejson as json 

# Setup the arguments this script can accept from the command line 
parser = optparse.OptionParser() 
parser.add_option('-p','--pickled_data_path',dest="pickled_data_path",type="string",help="Path to the file containing pickled data.") 
parser.add_option('-j','--json_data_path',dest="json_data_path",type="string",help="Path to where the json data should be saved.") 
opts,args=parser.parse_args() 

# Load in the pickled data from either a file or the standard input stream 
if opts.pickled_data_path: 
    unpickled_data = cPickle.loads(open(opts.pickled_data_path).read()) 
else: 
    unpickled_data = cPickle.loads(sys.stdin.read()) 

# Output the json version of the data either to another file or to the standard output 
if opts.json_data_path: 
    open(opts.json_data_path, 'w').write(json.dumps(unpickled_data)) 
else: 
    print json.dumps(unpickled_data) 

esta manera, si su conseguir los datos de un archivo que podría hacer algo como esto:

<?php 
    exec("python pickle2json.py -p pickled_data.txt", $json_data = array()); 
?> 

o si desea guardarlo en un archivo de esto:

<?php 
    system("python pickle2json.py -p pickled_data.txt -j p_to_j.json"); 
?> 

Todo el código anterior, probablemente no es perfecto (no soy un desarrollador de PHP), pero sería algo así como este trabajo para usted?

1

Si el pickle está siendo creado por el código que mostró, entonces no contendrá datos binarios, a menos que llame a newlines "datos binarios". Ver the Python docs. El siguiente código fue ejecutado por Python 2.6.

>>> import cPickle 
>>> data = {'user_id': 5} 
>>> for protocol in (0, 1, 2): # protocol 0 is the default 
...  print protocol, repr(cPickle.dumps(data, protocol)) 
... 
0 "(dp1\nS'user_id'\np2\nI5\ns." 
1 '}q\x01U\x07user_idq\x02K\x05s.' 
2 '\x80\x02}q\x01U\x07user_idq\x02K\x05s.' 
>>> 

¿Cuál de las opciones anteriores se parece más a lo que está viendo? ¿Puedes publicar el contenido del archivo encurtido como se muestra en un editor/volcador hexadecimal o lo que sea el equivalente de PHP de repr() de Python? ¿Cuántos elementos en un diccionario típico? ¿Qué tipos de datos son distintos de "entero" y "cadena de bytes de 8 bits" (¿qué codificación?)?

0

Tuve el mismo problema. No encontré una solución, así que he creado mi propio módulo de puerto de pitón minimalista en php. Más tarde encontré Zend Serializer Adapter PythonPickle de Zend Framework.