这已经让我咬了很长一段时间了。我有一个通过序列化一些Python Dict对象生成的以下pickle文件(名为rawFile.raw):
rawFile.raw的内容(为易读性而截断):
(dp0
S'request_body # 1'
p1
S''
p2
sS'port # 1'
p3
I80
sS'query_params # 1'
p4
ccopy_reg
_reconstructor
p5
(cnetlib.odict
ODict
p6
c__builtin__
object
p7
Ntp8
Rp9
(dp10
S'lst'
p11
(lp12
(S'layoutId'
p13
S'-1123196643'
p14
tp15
asbsS'headers # 1'
p16
g5
(cnetlib.odict
ODictCaseless
p17
g7
Ntp18
Rp19
(dp20
g11
(lp21
(lp22
S'sn'
p23
aS'2.VI7D9DF640615B4948854C88C5E769B94C.SIE5FB3A28D0DA4F27A3D2C03B8FAAFFAE.VS144257070601359422212.1442570840'
p24
aa(lp25
S'Browser-Name'
p26
aS'Mobile Safari'
p27
aa(lp28
S'Accept-Encoding'
p29
aS'gzip'
p30
aa(lp31
S'secureToken'
p32
aS'5nANXZrwYBrl9sNykA+qlpLsjHXlnF97tQLHnPgcjwZm9u0t8XAHtO4XTjKODcIb0ee4LlFchmUiptWZEPDUng=='
p33
aa(lp34
S'User-Agent'
p35
aS'Mozilla/5.0 (Linux; U; Android 4.3; en-us; Google Galaxy Nexus - 4.3 - API 18 - 720x1280 Build/JLS36G) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 FKUA/Retail/590206/Android/Mobile (Genymotion/Google Galaxy Nexus - 4.3 - API 18 - 720x1280/fd6babaa1ff9127ed7e9cc7a916639e5)'
p36
aa(lp37
S'Device-Id'
p38
aS'fd6babaa1ff9127ed7e9cc7a916639e5'
p39
aa(lp40
S'Host'
p41
aS'mobileapi.flipkart.net'
p42
aa(lp43
S'Connection'
p44
aS'Keep-Alive'
p45
aasbsS'method # 1'
p46
S'GET'
p47
sS'scheme # 1'
p48
S'http'
p49
sS'path # 1'
p50
(lp51
S'3'
p52
aS'layout'
p53
aS'widget'
p54
aS'productBundle'
p55
as.(dp0
S'request_body # 1'
p1
S''
p2
sS'method # 1'
p3
S'GET'
p4
sS'query_params # 2'
p5
ccopy_reg
_reconstructor
p6
(cnetlib.odict
ODict
p7
c__builtin__
object
p8
Ntp9
Rp10
(dp11
S'lst'
p12
(lp13
sbsS'query_params # 1'
p14
...更多类似的内容被截断。
现在我需要将此文件的内容存储在MySql表的列中。通过一些谷歌搜索,我了解到这些应该存储在BLOB列中。所以我做了。另外,如果你观察到,上面的内容也有很多单引号和(可能有)双引号。我正在使用MySqlDB python连接器。因此,当我尝试将以上数据插入相应的列中时:
INSERT INTO session_logs(request_as_on, session_pickle) VALUES (%s, %s)
然后
self.cur.execute(insertValueQry,(parser.parse(reqTimeStamp).strftime('%Y-%m-%d %H:%M:%S'), putThisPickleInDb))
我收到以下错误:
插入错误1241时出现 mysqldb插入错误:操作数应包含1列
因此,为了解决上述问题,我将上述执行语句替换为:
self.cur.execute(insertValueQry,(parser.parse(reqTimeStamp).strftime('%Y-%m-%d %H:%M:%S'), self.con.escape_string(str(putThisPickleInDb))))
它通过从pickle数据中转义所有单引号和双引号来解决问题。但它不会以与原始文件中相同的格式存储表中的数据。
显然因此,现在我需要从数据库读回这个泡菜内容,
它仍然被转义 - 所以我执行以下操作以取消它并获取原始内容:
aalu = "" <br>
aalu = aalu + str(userSelectedSessionPickle[0]).decode('string_escape').decode('string_escape')
其中userSelectedSessionPickle是从db。
返回的元组在取消它之后,我尝试用以下方法再次制作一个泡菜:
pickle.dump (aalu, currentPickleRawFile)
这样我以后可以加载pickle文件并根据需要使用它。但是当对文件currentPickleRawFile执行pickle.load时,会抛出以下错误:
ValueError:字典更新序列元素#0的长度为1; 2是必需的
以防万一有用:当我在文本编辑器中打开文件currentPickleRawFile时,其中的内容格式与rawFile.raw中的内容格式不同(上面显示的内容)。
我需要的只是将上面的pickle文件存储在数据库中,然后才能将其加载回来。我怎样才能完成这项工作?
答案 0 :(得分:3)
说我想出解决方案是不公正的。我必须,必须提及这个天使博客,这个博客终于来到我的救援,并帮助我完成我的工作,这几乎让我疯狂了。
http://blog.cameronleger.com/2011/05/31/python-example-pickling-things-into-mysql-databases/
看起来他将pickle插入数据库的方式就是这样做的。
正如有人在下面的评论中所建议的,如果博客已经死亡,我们会再次解决问题。所以这里是博客文章中的代码段复制粘贴:
import cPickle
import MySQLdb
## Create a semi-complex list to pickle
listToPickle = [(10, 10), (20, 10.0), (1.0, 2.0)]
## Pickle the list into a string
pickledList = cPickle.dumps(listToPickle)
## Connect to the database as localhost, user pickle,
## password cucumber, database lists
connection = MySQLdb.connect('localhost','pickle','cucumber','lists')
## Create a cursor for interacting
cursor = connection.cursor()
## Add the information to the database table pickleTest
cursor.execute("""INSERT INTO pickleTest VALUES (NULL, 'testCard', %s)""", (pickledList, ))
## Select what we just added
cursor.execute("""SELECT features FROM pickleTest WHERE card = 'testCard'""")
## Dump the results to a string
rows = cursor.fetchall()
## Get the results
for each in rows:
## The result is also in a tuple
for pickledStoredList in each:
## Unpickle the stored string
unpickledList = cPickle.loads(pickledStoredList)
print unpickledList
答案 1 :(得分:1)
如果你想在sql表或sql数据库中存储pickle对象,那么有一个名为klepto
的包(我写的)允许你透明地执行它。由于您有兴趣将字典存储在sql表中作为单个对象,我将在下面执行此操作...但您可以存储任何对象。 klepto
用于将字典条目映射到数据库或表。
>>> import klepto
>>> # dump to the sql archive
>>> d = klepto.archives.sql_archive('mysql')
>>> a = dict(a=1,b=2,c=3,d=min,e=lambda x:x,f=[1,2,3,4,5])
>>> d['x'] = a
>>> d.dump()
>>> del d, a
>>>
>>> # read from the sql archive
>>> d = klepto.archives.sql_archive('mysql')
>>> d.load()
>>> a = d['x']
>>> a
{'a': 1, 'c': 3, 'b': 2, 'e': <function <lambda> at 0x103aa9848>, 'd': <built-in function min>, 'f': [1, 2, 3, 4, 5]}
>>>
>>> # different options for klepto backends
>>> klepto.archives.sql_archive
<class 'klepto.archives.sql_archive'>
>>> klepto.archives.sqltable_archive
<class 'klepto.archives.sqltable_archive'>
>>> klepto.archives.file_archive
<class 'klepto.archives.file_archive'>
>>> klepto.archives.dir_archive
<class 'klepto.archives.dir_archive'>