Python的cPickle在PHP中如何反序列化?

6

我需要在PHP中反序列化一个使用Python中的cPickle序列化的字典。

在这种特定情况下,我可能只需使用正则表达式获取所需信息,但是否有更好的方法?有没有PHP扩展可以更自然地反序列化整个字典?

显然,它是像这样在Python中序列化的:

import cPickle as pickle

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

这种序列化的内容无法轻松地粘贴到此处,因为它包含二进制数据。


3
你提到序列化不在你的控制范围内。你是通过什么方式接收这些pickle数据的?是本地文件吗? - Eric Palakovich Carr
它来自Django数据库,是django session表中的session_data。我可能最终会编写SessionMiddleware以将session_data序列化为JSON。我只希望不必修改Django应用程序来实现这一点。 - Ciantic
4个回答

6
如果你想在不同编程语言的程序之间共享数据对象,使用类似 JSON 的序列化/反序列化可能会更容易。大多数主要编程语言都有 JSON 库。

2
Python 2.6+内置了它,并且较早版本可使用simplejson。 - Ignacio Vazquez-Abrams
3
虽然是个好主意,但序列化部分不在我的控制范围内。 - Ciantic
我最初认为我不想黑掉Django应用程序,但是再想一想,这可能是更快的解决方案。因此,这里是我为Django编写的简单JSON SessionStore - Ciantic

5

您能执行系统调用吗?您可以使用类似这样的Python脚本将pickle数据转换为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)

这样,如果您从文件中获取数据,可以这样做:
<?php
    exec("python pickle2json.py -p pickled_data.txt", $json_data = array());
?>

如果您想将它保存到文件中,可以使用以下方法:

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

上面的代码可能不完美(我不是PHP开发人员),但是这样的东西对你是否有用呢?

3

我知道这已经很古老了,但我刚刚需要为一个Django 1.3应用程序(约于2012年)执行此操作,并找到了以下内容:

https://github.com/terryf/Phpickle

所以以防万一,如果有人今后也需要相同的解决方案。


1
如果pickle是由你展示的代码创建的,那么它不会包含二进制数据——除非你将换行符称为“二进制数据”。请参阅Python文档。以下代码是在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.'
>>>

以上哪一个看起来最像你所看到的?你能够发布通过十六进制编辑器/转储器显示的腌制文件内容,或者是 PHP 中类似于 Python 的 repr() 函数的等价物吗?一个典型字典中有多少项?除了“整数”和“8位字节字符串”(使用什么编码?)之外还有哪些数据类型?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接