144

我需要将一个小dict对象保存到磁盘,它的键是类型str,值是ints ,然后恢复它。像这样的东西:

{'juanjo': 2, 'pedro':99, 'other': 333}

什么是最好的选择,为什么?pickle用或序列化它simplejson

我正在使用 Python 2.6。

4

7 回答 7

116

对于我的序列化,我更喜欢 JSON 而不是 pickle。Unpickling 可以运行任意代码,pickle用于在程序之间传输数据或在会话之间存储数据是一个安全漏洞。JSON 不会引入安全漏洞并且是标准化的,因此如果您需要,可以通过不同语言的程序访问数据。

于 2010-02-13T22:33:07.943 回答
82

如果您没有任何互操作性要求(例如,您只是将数据与 Python 一起使用)并且二进制格式很好,请使用cPickle,它可以为您提供非常快速的 Python 对象序列化。

如果您想要互操作性或者您想要一种文本格式来存储您的数据,请使用 JSON(或其他一些适当的格式,具体取决于您的约束)。

于 2010-02-13T22:22:51.170 回答
45

您可能还会发现这很有趣,可以比较一些图表:http: //kovshenin.com/archives/pickle-vs-json-which-is-faster/

于 2011-06-02T14:30:41.577 回答
26

如果您主要关心速度和空间,请使用 cPickle,因为 cPickle 比 JSON 更快。

如果您更关心互操作性、安全性和/或人类可读性,请使用 JSON。


其他答案中引用的测试结果记录在 2010 年,2016 年使用 cPickle协议 2进行的更新测试显示:

  • cPickle 加载速度提高 3.8 倍
  • cPickle 读取速度提高 1.5 倍
  • cPickle 编码略小

自己用这个 gist重现这个,它基于其他答案中引用的Konstantin 基准,但是使用带有协议 2 的 cPickle 而不是 pickle,并使用 json 而不是 simplejson(因为json 比 simplejson 快),例如

wget https://gist.github.com/jdimatteo/af317ef24ccf1b3fa91f4399902bb534/raw/03e8dbab11b5605bc572bc117c8ac34cfa959a70/pickle_vs_json.py
python pickle_vs_json.py

在不错的 2015 Xeon 处理器上使用 python 2.7 的结果:

Dir Entries Method  Time    Length

dump    10  JSON    0.017   1484510
load    10  JSON    0.375   -
dump    10  Pickle  0.011   1428790
load    10  Pickle  0.098   -
dump    20  JSON    0.036   2969020
load    20  JSON    1.498   -
dump    20  Pickle  0.022   2857580
load    20  Pickle  0.394   -
dump    50  JSON    0.079   7422550
load    50  JSON    9.485   -
dump    50  Pickle  0.055   7143950
load    50  Pickle  2.518   -
dump    100 JSON    0.165   14845100
load    100 JSON    37.730  -
dump    100 Pickle  0.107   14287900
load    100 Pickle  9.907   -

带有 pickle 协议 3 的 Python 3.4 甚至更快。

于 2016-09-21T03:42:36.700 回答
13

JSON 还是泡菜?JSON和泡菜怎么样!

您可以使用jsonpickle. 它易于使用,并且磁盘上的文件是可读的,因为它是 JSON。

请参阅jsonpickle 文档

于 2010-02-13T22:55:10.170 回答
8

我尝试了几种方法,发现使用 cPickle 并将转储方法的协议参数设置为:cPickle.dumps(obj, protocol=cPickle.HIGHEST_PROTOCOL)是最快的转储方法。

import msgpack
import json
import pickle
import timeit
import cPickle
import numpy as np

num_tests = 10

obj = np.random.normal(0.5, 1, [240, 320, 3])

command = 'pickle.dumps(obj)'
setup = 'from __main__ import pickle, obj'
result = timeit.timeit(command, setup=setup, number=num_tests)
print("pickle:  %f seconds" % result)

command = 'cPickle.dumps(obj)'
setup = 'from __main__ import cPickle, obj'
result = timeit.timeit(command, setup=setup, number=num_tests)
print("cPickle:   %f seconds" % result)


command = 'cPickle.dumps(obj, protocol=cPickle.HIGHEST_PROTOCOL)'
setup = 'from __main__ import cPickle, obj'
result = timeit.timeit(command, setup=setup, number=num_tests)
print("cPickle highest:   %f seconds" % result)

command = 'json.dumps(obj.tolist())'
setup = 'from __main__ import json, obj'
result = timeit.timeit(command, setup=setup, number=num_tests)
print("json:   %f seconds" % result)


command = 'msgpack.packb(obj.tolist())'
setup = 'from __main__ import msgpack, obj'
result = timeit.timeit(command, setup=setup, number=num_tests)
print("msgpack:   %f seconds" % result)

输出:

pickle         :   0.847938 seconds
cPickle        :   0.810384 seconds
cPickle highest:   0.004283 seconds
json           :   1.769215 seconds
msgpack        :   0.270886 seconds
于 2017-12-12T02:42:55.957 回答
5

就个人而言,我通常更喜欢 JSON,因为数据是人类可读的。当然,如果您需要序列化 ​​JSON 不会采用的东西,那么请使用 pickle。

但是对于大多数数据存储,您不需要序列化任何奇怪的东西,而且 JSON 更容易,并且始终允许您在文本编辑器中将其弹出并自己检查数据。

速度不错,但对于大多数数据集来说,差异可以忽略不计;无论如何,Python 通常不会太快。

于 2014-06-26T12:35:06.617 回答