Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python对象持久性_Python_Persistence - Fatal编程技术网

Python对象持久性

Python对象持久性,python,persistence,Python,Persistence,我正在寻求有关在Python中实现对象持久性的方法的建议。更准确地说,我希望能够将Python对象链接到文件,这样任何打开该文件表示的Python进程都可以共享相同的信息,任何进程都可以更改其对象,并且更改将传播到其他进程,即使“存储”该对象的所有进程都已关闭,该文件将保留,并可由其他进程重新打开 在我的Python发行版中,我发现了这方面的三个主要候选对象—anydbm、pickle和shelve(dbm看起来很完美,但它仅限于Unix,我使用的是Windows)。然而,它们都有缺陷: an

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

在我的Python发行版中,我发现了这方面的三个主要候选对象—anydbm、pickle和shelve(dbm看起来很完美,但它仅限于Unix,我使用的是Windows)。然而,它们都有缺陷:

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

我可以通过创建我自己的使用pickle的模块来实现这种行为,并编辑转储和加载行为,以便它们使用我上面提到的重复读取——但我发现很难相信,这个问题以前从未发生过,也从未被更有天赋的程序员解决过。此外,这些重复读取对我来说似乎效率低下(尽管我必须承认,我对操作复杂性的了解是有限的,而且这些重复读取有可能是在“幕后”进行的,而不是在shelve等显然更平滑的模块中进行的)。因此,我的结论是,我肯定缺少了一些代码模块来解决我的问题。如果有人能为我指出正确的方向,或就实现提供建议,我将不胜感激。

请改用(Zope对象数据库)。以ZEO为后盾,它满足您的要求:

  • Python对象的透明持久性

    ZODB在下面使用pickle,所以任何可以pickle的东西都可以存储在ZODB对象存储中

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

    这意味着,当一个进程的更改良好且准备就绪时,这些更改会传播到所有其他进程,并且每个进程在整个事务中都具有一致的数据视图

ZODB已经存在十多年了,所以您可以正确地推测,这个问题以前已经解决了。:-)

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

一些ZODB存储是围绕其他存储的包装,用于添加功能;例如,DemoStorage将更改保存在内存中,以便于单元测试和演示设置(重新启动,您就可以重新开始)。BeforeStorage为您提供了一个时间窗口,只返回给定时间点之前的事务数据。后者对我来说有助于恢复丢失的数据

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


同样可以通过将ZODB数据存储在关系数据库(如PostgreSQL、MySQL或Oracle)中来实现。

对于初学者,您可以将搁置数据库移植到ZODB数据库,如下所示:

#!/usr/bin/env python
import shelve
import ZODB, ZODB.FileStorage
import transaction
from optparse import OptionParser
import os
import sys
import re

reload(sys)
sys.setdefaultencoding("utf-8")

parser = OptionParser()

parser.add_option("-o", "--output", dest = "out_file", default = False, help ="original shelve database filename")
parser.add_option("-i", "--input", dest = "in_file", default = False, help ="new zodb database filename")

parser.set_defaults()
options, args = parser.parse_args()

if options.in_file == False or options.out_file == False :
    print "Need input and output database filenames"
    exit(1)

db = shelve.open(options.in_file, writeback=True)
zstorage = ZODB.FileStorage.FileStorage(options.out_file)
zdb = ZODB.DB(zstorage)
zconnection = zdb.open()
newdb = zconnection.root()

for key, value in db.iteritems() :
    print "Copying key: " + str(key)
    newdb[key] = value

transaction.commit()

我建议使用TinyDB,它更好,使用更简单


看看
mongo db
。它没有像上面的例子那样完全集成到语言中,但它将为您提供一个比对文件系统进行酸洗和在锁方面更健壮、更宽容的数据库。ZODB听起来正是我想要的(RelStorage听起来像是未来有趣的东西)-谢谢!我会测试它,如果它对我有效,我会把它标记为已回答。这听起来也是我想要的;在架子上提供什么。
#!/usr/bin/env python
import shelve
import ZODB, ZODB.FileStorage
import transaction
from optparse import OptionParser
import os
import sys
import re

reload(sys)
sys.setdefaultencoding("utf-8")

parser = OptionParser()

parser.add_option("-o", "--output", dest = "out_file", default = False, help ="original shelve database filename")
parser.add_option("-i", "--input", dest = "in_file", default = False, help ="new zodb database filename")

parser.set_defaults()
options, args = parser.parse_args()

if options.in_file == False or options.out_file == False :
    print "Need input and output database filenames"
    exit(1)

db = shelve.open(options.in_file, writeback=True)
zstorage = ZODB.FileStorage.FileStorage(options.out_file)
zdb = ZODB.DB(zstorage)
zconnection = zdb.open()
newdb = zconnection.root()

for key, value in db.iteritems() :
    print "Copying key: " + str(key)
    newdb[key] = value

transaction.commit()