繁体   English   中英

如何将一个python字典腌制成MySQL?

[英]How to Pickle a python dictionary into MySQL?

我查看了几个SO-Questions,了解如何挑选python对象并将其存储到数据库中。 我收集的信息是:

  • import pickleimport cpickle 如果性能有问题,请导入后者。
  • 假设dict是一个python字典(或者所谓的python对象): pickled = pickle.dumps(dict)
  • 使用什么模块与数据库进行通信,将商店pickled成MySQL BLOB列。
  • 再来一次。 并使用pickle.loads(pickled)来恢复python字典。

我只是想确保我明白这一点。 我错过了一些关键的东西吗 有副作用吗? 这真的很容易吗?

背景信息:我唯一想做的就是存储Googlegeocoder-Responses,在我的例子中是嵌套的python dictionarys。 我只使用响应对象的一小部分,我不知道以后是否需要更多的响应对象。 这就是为什么我想存储响应以节省我重复几百万个查询的原因。

它真的那么简单......只要你不需要你的数据库知道关于字典的任何信息。 如果您需要对字典内容进行任何类型的结构化数据访问,那么您将需要更多地参与其中。

另一个问题可能是你打算把它放在dict中。 Python的pickle序列化非常智能,可以处理大多数情况,而无需添加自定义支持。 但是,当它不起作用时,很难理解出了什么问题。 因此,如果可以,请将dict的内容限制为Python的内置类型。 如果您开始添加自定义类的实例,请将它们保留为简单的自定义类,这些类不会对属性存储或访问执行任何有趣的操作。 并注意从附加组件添加类或类型的实例。 通常,如果您开始遇到难以理解的酸洗或去除污染问题,请查看dict中的非内置类型。

如果速度非常重要,我只是运行了一个测试,从一个pickle加载一个大的python字典(35MB)与从MySql表中的SELECTING加载所有键和值存储在行中:

泡菜方法:

import time, pickle
t1 = time.clock()
f = open('story_data.pickle','rb')
s = pickle.load(f)
print time.clock() - t1

MySQL方法:

import database as db
t1 = time.clock()
data,msg = db.mysql(""" SELECT id,story from story_data;""")
data_dict = dict([(int(x),y.split(',')) for x,y in data])
print time.clock() - t1

输出:pickle方法:32.0785171704 mysql方法:3.25916336479

如果十倍速度增强就足够了,数据库的结构可能无关紧要。 注意我将所有逗号分隔数据拆分为列表作为36,000个键的值,它仍然只需要3秒。 所以我已经不再使用泡菜来处理大型数据集,因为我使用的400线程序的其余部分耗时约3秒,而泡菜加载需要32秒。

另请注意:

cPickle就像pickle一样工作,速度提高了50%以上。

不要试图挑选一个充满字典并保存在mysql中的类:它没有正确地重建自己,至少它不适合我。

如果你有嵌套的词典,你必须要小心。 大多数python对象都没有pickle(你可以将任何对象填充为dict的值)。 更糟糕的是,更少的python对象可以转换为字符串并存储在SQL中。

但是,如果使用klepto ,则数据库中的序列化和存储非常透明,适用于大多数python对象。

让我们在dict (或dicts)中构建一些典型的python对象:

>>> class Foo(object):                                 
...   def bar(self, x):
...     return self.y + x
...   y = 1
... 
>>> d1 = {'a': min, 'b': lambda x:x**2, 'c': [1,2,3], 'd': Foo()}
>>> f = Foo(); f.y = 100
>>> d2 = {'a': max, 'b': lambda x:x**3, 'c': [2,1,3], 'd': f}

现在,让我们构建一个嵌套的dict ,并转储到MYSQL存档。

>>> import klepto
>>> a = klepto.archives.sql_archive('mysql://user:pass@localhost/foo', dict={'d1':d1, 'd2':d2})
>>> a.dump()

现在,我们删除了归档的界面......并构建一个新的界面。 load将所有对象加载到内存中。

>>> del a
>>> b = klepto.archives.sql_archive('mysql://user:pass@localhost/foo')
>>> b.load()

我们现在访问内存中的副本。

>>> b['d1']
{'a': <built-in function min>, 'c': [1, 2, 3], 'b': <function <lambda> at 0x1037ccd70>, 'd': <__main__.Foo object at 0x103938ed0>}
>>> b['d1']['b'](b['d1']['d'].bar(1))
4
>>> b['d2']['b'](b['d2']['d'].bar(1))
1030301
>>> 

我们退出python ...然后启动一个新的会话。 这次,我们决定使用cached=False ,因此我们将直接与数据库进行交互。

dude@hilbert>$ python
Python 2.7.10 (default, May 25 2015, 13:16:30) 
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import klepto
>>> b = klepto.archives.sql_archive('mysql://user:pass@localhost/foo', cached=False)
>>> b['d2']['b'](b['d2']['d'].bar(1))
1030301
>>> b['d1']['b'](b['d1']['d'].bar(1))
4
>>> 

klepto利用sqlalchemy ,因此它可以在多个后端数据库......,另外,提供了相同的dict基于接口的磁盘存储(在一个文件或目录)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM