可以将Python字典序列化到sqlite3文本字段吗?

44 投票
14 回答
34381 浏览
提问于 2025-04-11 09:29

有没有什么需要注意的地方?我可以把它存放在文本字段里,还是必须用二进制大对象(blob)?
(我对pickle和sqlite都不是很熟悉,所以我想确认一下我的一些高层设计想法是不是在正确的方向上。)

14 个回答

10

我写了一篇关于这个想法的博客,不过我用的是json,而不是pickle,因为我想让它能和perl以及其他程序一起使用。

http://writeonly.wordpress.com/2008/12/05/simple-object-db-using-json-and-python-sqlite/

从架构上看,这是一种快速且简单的方法,可以让任意数据结构实现持久化、事务等功能。我发现这种组合在我需要持久化数据时特别有用,而且在sql层面上不需要做太多操作(或者在sql中处理起来非常复杂,而用生成器处理则简单得多)。

代码本身也很简单:

#  register the "loader" to get the data back out.
sqlite3.register_converter("pickle", cPickle.loads) 

然后,当你想把它存入数据库时,

p_string = p.dumps( dict(a=1,b=[1,2,3]))  
conn.execute(''' 
   create table snapshot( 
      id INTEGER PRIMARY KEY AUTOINCREMENT, 
        mydata pickle); 
''')  

conn.execute(''' 
    insert into snapshot values 
    (null, ?)''', (p_string,))
''')
61

我也需要实现同样的功能。

这让我费了不少脑筋,直到我终于搞明白了,多亏了这篇文章,我才知道怎么在二进制格式下让它正常工作。

插入/更新数据:

pdata = cPickle.dumps(data, cPickle.HIGHEST_PROTOCOL)
curr.execute("insert into table (data) values (:data)", sqlite3.Binary(pdata))

你必须给dumps函数传递第二个参数,这样才能强制使用二进制格式进行序列化。
另外,记得使用sqlite3.Binary,这样才能把数据放进BLOB字段里。

获取数据:

curr.execute("select data from table limit 1")
for row in curr:
  data = cPickle.loads(str(row['data']))

当你获取BLOB字段的数据时,sqlite3会得到一个'buffer'类型的数据,这个数据需要用str函数转换成字符串,然后才能传给loads方法。

23

如果你想存储一个被“腌制”的对象(这是一种数据处理方式),你需要用到一个叫做“blob”的东西,因为它是二进制数据。不过,你可以把这个“腌制”的对象进行base64编码,这样就能得到一个可以存储在文本字段里的字符串。

不过,通常来说,这种做法可能不是个好主意,因为你存储的是一种不透明的数据,这样一来,你就无法用SQL(一种数据库查询语言)对这些数据进行有用的操作了。不过,具体情况我也不太清楚,所以没法对这个做法下定论。

撰写回答