泡椒还是json?

Jua*_*nti 107 python json pickle

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

{'juanjo': 2, 'pedro':99, 'other': 333}
Run Code Online (Sandbox Code Playgroud)

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

我使用的是Python 2.6.

Mik*_*ham 96

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

  • 人们可以创造一种泡菜病毒,它可以将自己腌制成加载后腌制的所有食物.有了json这是不可能的. (4认同)
  • 尽管当前应用程序中的安全风险可能较低,但是JSON允许您完全关闭整个过程。 (2认同)
  • 除了安全性,JSON还具有其他优点,它使迁移变得容易,因此您可以加载由较早版本的应用程序保存的数据。同时,您可以添加一个字段,或替换整个子结构。为dict / list编写这样的转换器(迁移)很简单,但是对于Pickle来说,要想转换之前,首先要加载它会很困难。 (2认同)
  • 我没有考虑过这方面(安全性和腌制对象运行任意代码的能力)。感谢您指出了这一点! (2认同)
  • “仅解封您信任的数据” - https://docs.python.org/3/library/pickle.html (2认同)

Håv*_*d S 65

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

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

  • JSON [似乎比cPickle更快](http://kovshenin.com/archives/pickle-vs-json-which-is-faster/). (44认同)
  • cPickle的最新协议现在比JSON更快.关于JSON更快的最新评论已经过时了几年.http://stackoverflow.com/a/39607169/1007353 (22认同)
  • @mac引用的基准测试只测试字符串.我单独测试了str,int和float,发现json比使用float序列化的cPickle慢,但是浮动反序列化更快.对于int(和str),json两种方式都更快.数据和代码:https://gist.github.com/marians/f1314446b8bf4d34e782 (14认同)
  • 我的观点是:没有真正的理由在JSON上使用基于你的前提的`cPickle`(或`pickle`).当我第一次阅读你的回答时,我认为原因可能是速度,但因为事实并非如此...... :) (10认同)
  • 我的回答强调了我认为在选择任一解决方案时最重要的考虑因素.我没有声称要么比另一个更快.如果JSON更快且其他方面合适,请使用JSON!(即,你没有理由进行投票.) (5认同)
  • @JDiMatteo:我怀疑如果测试套件使用协议 2(自 2.3 版左右可用,但不是出于向后兼容原因的默认设置)而不是默认的 Python 2 协议,即使在发表评论时,`cPickle` 也会更快, 0. 0 受到严重限制,每个字节仅使用 8 位中的 7 位(这对必须重新编码的原始二进制数据造成很大伤害,而不是转储原始数据),不能很好地支持新式类等。 协议2 使用 `cPickle`(或在 Python 3 上,使用默认协议 3 或更高版本的普通 `pickle`)可能会在所有情况下击败 JSON,除了最人为的情况。 (2认同)
  • JSON的一个(可能是次要的)下方:JSON没有元组.串行化/反序列化后,python元组最终将成为一个列表.如果您的数据包含元组并且您希望将它们反序列化为元组,则需要避免使用JSON. (2认同)

kov*_*nin 43

你可能也会觉得这很有趣,有些图表可供比较:http://kovshenin.com/archives/pickle-vs-json-which-is-faster/

  • 正是我所寻找的那种比较,谢谢! (5认同)
  • [在Python 3.4中,`pickle`在`int`,`str`和`float`上跳过`json`.(http://stackoverflow.com/a/26860404/819417) (4认同)

JDi*_*teo 19

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

如果您更关注互操作性,安全性和/或人类可读性,那么请使用JSON.


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

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

与此重现自己这个要点,这是基于康斯坦丁的基准在其他的答案中引用,但使用的cPickle按方案2的替代泡菜,并使用JSON而不是simplejson(因为JSON比simplejson更快),例如

wget https://gist.github.com/jdimatteo/af317ef24ccf1b3fa91f4399902bb534/raw/03e8dbab11b5605bc572bc117c8ac34cfa959a70/pickle_vs_json.py
python pickle_vs_json.py
Run Code Online (Sandbox Code Playgroud)

在一个体面的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   -
Run Code Online (Sandbox Code Playgroud)

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


Pau*_*ndt 11

JSON还是泡菜?JSON 泡菜怎么样!你可以用jsonpickle.它易于使用,磁盘上的文件是可读的,因为它是JSON.

http://jsonpickle.github.com/

  • 有没有人根据选项对其性能进行基准测试?它的性能是否与原始json相当,如http://www.benfrederickson.com/dont-pickle-your-data/? (2认同)

Ahm*_*akr 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)
Run Code Online (Sandbox Code Playgroud)

输出:

pickle         :   0.847938 seconds
cPickle        :   0.810384 seconds
cPickle highest:   0.004283 seconds
json           :   1.769215 seconds
msgpack        :   0.270886 seconds
Run Code Online (Sandbox Code Playgroud)


ric*_*agy 5

就个人而言,我通常更喜欢 JSON,因为数据是人类可读的。当然,如果您需要序列化 ​​JSON 不支持的内容,请使用 pickle。

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

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

  • [在 Python 3.4 中,`pickle` 的速度是 `json` 的两倍多。](http://stackoverflow.com/a/26860404/819417) (3认同)