为什么我们应该选择将序列化的数据而不是原始代码存储到数据库?

2024-04-19 22:29:19 发布

您现在位置:Python中文网/ 问答频道 /正文

如果我们有一些代码(数据结构)应该存储在数据库中,总有人建议我们存储序列化的数据,而不是原始的代码字符串。在

所以我不太确定为什么我们应该选择序列化数据。在

给出一个简单的实例(在python中):

我们有一个字段可以存储python的dict,比如

{ "name" : "BMW", "category":"car", "cost" : "200000"}

所以我们可以使用pickle(python模块)序列化它,然后将pickle数据存储到db字段。在

或者我们可以直接将dict字符串存储到DB而不需要序列化。在

因为我们需要将字符串转换回python数据,所以两种方法都很容易实现,通过使用酸洗负荷和执行官。在

那么哪一个更适合呢?为什么呢?是因为exec比pickle慢得多吗?或者其他原因?在

谢谢。在


Tags: 数据实例字符串代码name数据库数据结构序列化
3条回答

Or we can store the dict string directly to DB without serializing.

没有所谓的“dict字符串”。有很多方法可以将dict序列化为字符串;您可能认为repr,可能是eval作为获取dict的方法(您提到了exec,但这很荒谬:您将执行什么语句。。。?!我想你可能是说eval)。它们的权衡是不同的序列化方法,在许多情况下,权衡往往倾向于pickle(cPickle,为了速度,协议-1通常意味着“你能做的最好的”)。在

性能当然是一个问题,例如,就存储的大小而言…:

$ python -c 'import cPickle; d=dict.fromkeys(range(99), "banana"); print len(repr(d))'
1376
$ python -c 'import cPickle; d=dict.fromkeys(range(99), "banana"); print len(cPickle.dumps(d,-1))'
412

…为什么每次序列化像这样的dict时都要存储1.4kb而不是0.4kb。。。?-)在

编辑:由于有人建议使用Json,因此值得指出的是,Json在这里需要1574个字节——甚至比笨重的repr还要大!在

至于速度。。。在

^{pr2}$

…为什么要花10倍的时间?有什么好处可以让你付出如此高昂的代价?在

编辑:json需要2.7毫秒秒——几乎是cPickle的40倍。在

还有一个通用性——并不是每个可序列化的对象都可以正确地使用repr和eval进行往返,而pickle则更为通用。E、 g.:

$ python -c'def f(): pass
d={23:f}
print d == eval(repr(d))'
Traceback (most recent call last):
  File "<string>", line 3, in <module>
  File "<string>", line 1
    {23: <function f at 0x241970>}
         ^
SyntaxError: invalid syntax

$ python -c'import cPickle
def f(): pass
d={"x":f}
print d == cPickle.loads(cPickle.dumps(d, -1))'
True

编辑:就往返而言,json甚至不如repr一般。在

因此,比较两种序列化方法(pickling vs repr/eval),我们可以看到:pickling更通用,它可以快10倍,占用数据库空间少3倍。在

您认为repr/eval有哪些补偿优势。。。?在

顺便说一句,我看到一些答案提到了安全性,但这并不是真正的要点:pickling也不安全(eval'untrusted string的安全性问题可能更明显,但是取消对不可信字符串的抓取也是不安全的,尽管是以更微妙和更黑暗的方式)。在

编辑:json更安全。这是否值得在规模、速度和通用性方面付出巨大代价,这是一个值得深思的权衡。在大多数情况下都不会。在

我更喜欢使用JSON之类的标准序列化格式在数据库中存储此类数据。它使数据的使用者可以用python以外的其他语言编写,基本上是人类可读的,而且使用SQL比pickled对象更容易查询。在

存储为字符串和使用pickle都是序列化策略。Pickle的存储方式更灵活,也更紧凑。两种策略,eval(在本例中,您将使用eval而不是exec)和酸洗负荷都是不安全的,这两个都可以运行任意Python代码。在

最好使用JSON(2.6中的JSON模块,simplejson第三方模块pre-2.6版本)之类的序列化格式,这种格式与Python读取无关,如果数据库中存在您不希望的数据,也不会执行任意代码。此外,pickle格式可能会发生变化(而且会丢失数据!),像JSON这样的标准不会以向后不兼容的方式对您进行更改。在

相关问题 更多 >