Python 对象持久化

标签 python persistence

我正在寻求有关在 Python 中实现对象持久性的方法的建议。更准确地说,我希望能够将一个 Python 对象链接到一个文件,这样任何打开该文件表示的 Python 进程都共享相同的信息,任何进程都可以更改其对象,并且更改将传播到其他进程,即使所有“存储”该对象的进程都已关闭,该文件仍将保留并可以由另一个进程重新打开。

我在我的 Python 发行版中找到了三个主要候选者——anydbm、pickle 和 shelve(dbm 看起来很完美,但它仅适用于 Unix,而我在 Windows 上)。然而,它们都有缺陷:

  • anydbm 只能处理字符串值的字典(我想存储一个字典列表,所有这些字典都有字符串键和字符串值,但理想情况下我会寻找一个没有类型限制的模块)
  • 搁置要求在更改传播之前重新打开文件 - 例如,如果两个进程 A 和 B 加载同一个文件(包含搁置的空列表),并且 A 添加一个项目到列表并调用 sync() , B 在重新加载文件之前仍会将列表视为空。
  • pickle(我目前用于我的测试实现的模块)具有与搁置相同的“重新加载要求”,并且也不会覆盖以前的数据 - 如果进程 A 将十五个空字符串转储到文件中,然后字符串 ' hello',进程 B 必须加载文件 16 次才能获得 'hello' 字符串。我目前正在处理这个问题,方法是在任何写入操作之前重复读取直到文件末尾(“在写入之前擦干净石板”),并通过重复每个读取操作直到文件末尾,但我觉得必须有更好的方法。

我理想中的模块的行为如下(“A>>>”代表进程 A 执行的代码,“B>>>”代表进程 B 执行的代码):

A>>> import imaginary_perfect_module as mod
B>>> import imaginary_perfect_module as mod
A>>> d = mod.load('a_file') 
B>>> d = mod.load('a_file')
A>>> d
{}
B>>> d
{}
A>>> d[1] = 'this string is one'
A>>> d['ones'] = 1   #anydbm would sulk here
A>>> d['ones'] = 11 
A>>> d['a dict'] = {'this dictionary' : 'is arbitrary', 42 : 'the answer'}
B>>> d['ones']   #shelve would raise a KeyError here, unless A had called d.sync() and B had reloaded d
11    #pickle (with different syntax) would have returned 1 here, and then 11 on next call
(etc. for B)

我可以通过创建自己的模块来实现此行为之前被更有才华的程序员修复过。此外,这些重复读取对我来说似乎效率低下(尽管我必须承认我对操作复杂性的了解是有限的,并且这些重复读取有可能在“幕后”进行,否则显然更平滑的模块(如搁置))。因此,我得出结论,我必须缺少一些可以为我解决问题的代码模块。如果有人能为我指明正确的方向,或提供有关实现的建议,我将不胜感激。

最佳答案

使用 ZODB (Zope 对象数据库)代替。在 ZEO 的支持下,它可以满足您的要求:

  • Python 对象的透明持久化

    ZODB 在底层使用 pickle,因此任何可 pickle 的东西都可以存储在 ZODB 对象存储中。

  • 完全兼容 ACID 的事务支持(包括保存点)

    这意味着当其他进程准备就绪时,一个进程的更改会传播到所有其他进程,并且每个进程对整个事务中的数据都有一致的看法。

ZODB 已经存在十多年了,所以您猜测这个问题之前已经解决了,这是正确的。 :-)

ZODB 让您插入存储;最常见的格式是 FileStorage,它将所有内容存储在一个 Data.fs 中,并为大型对象提供可选的 blob 存储。

一些 ZODB 存储是对其他存储的包装以添加功能;例如,DemoStorage 会在内存中保留更改,以促进单元测试和演示设置(重新启动,您将再次拥有干净的状态)。 BeforeStorage 为您提供一个时间窗口,仅返回给定时间点之前 的交易数据。后者对我恢复丢失的数据很有帮助。

ZEO就是这样一个引入客户端-服务器架构的插件。使用 ZEO 可以让您一次从多个进程访问给定的存储;如果您只需要从一个进程进行多线程访问,则不需要这一层。

同样可以用 RelStorage 实现,它将 ZODB 数据存储在关系数据库中,例如 PostgreSQL、MySQL 或 Oracle。

关于Python 对象持久化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10830869/

相关文章:

python - 从 Django 创建 SQL 插入脚本以填充 PostgreSQL 数据库

java - 在 Java 中接收不同的内容

python - 实现 Python 持久属性

java - 将属性注入(inject) JPQL SELECT 子句

arrays - 在 Swift 中归档和取消归档 DocumentDirectory 中的数组

sharepoint - 将文档存储在文件系统而不是 SharePoint 文档库中的数据库中

python - 如何使用gensim wikicorpus获取带有标点符号的维基百科语料库文本?

python - 区分 tarfile 中不同驱动器的文件

python - 如何从 PyQt4 中的 ComboBox 获取输入

python - PySolr 连接错误 404