Python搁置模块问题

Python搁置模块问题,python,shelve,Python,Shelve,Python搁置模块是否内置了任何保护,以确保两个进程不会同时写入文件?搁置模块使用底层数据库包(如dbm或bsddb) 报告说(我的重点): 搁置模块不支持对搁置对象的并发读/写访问。(多个同时读访问是安全的。)当一个程序有一个可供写入的工具架时,其他程序不应将其打开以供读取或写入。可以使用Unix文件锁定来解决此问题,但这在Unix版本中有所不同,需要了解所使用的数据库实现 结论:这取决于OS和基础DB。为了保持可移植性,不要建立在并发性的基础上。根据上面的答案,将多个编写器放在书架上是不安

Python搁置模块是否内置了任何保护,以确保两个进程不会同时写入文件?

搁置模块使用底层数据库包(如dbm或bsddb)

报告说(我的重点):

搁置模块不支持对搁置对象的并发读/写访问。(多个同时读访问是安全的。)当一个程序有一个可供写入的工具架时,其他程序不应将其打开以供读取或写入。可以使用Unix文件锁定来解决此问题,但这在Unix版本中有所不同,需要了解所使用的数据库实现


结论:这取决于OS和基础DB。为了保持可移植性,不要建立在并发性的基础上。

根据上面的答案,将多个编写器放在书架上是不安全的。我使货架更安全的方法是编写一个包装器,负责打开和访问货架元素。包装器代码如下所示:

def open(self, mode=READONLY):
    if mode is READWRITE:
        lockfilemode = "a" 
        lockmode = LOCK_EX
        shelve_mode = 'c'
    else:
        lockfilemode = "r"
        lockmode = LOCK_SH
        shelve_mode = 'r'
    self.lockfd = open(shelvefile+".lck", lockfilemode)
    fcntl.flock(self.lockfd.fileno(), lockmode | LOCK_NB)
    self.shelve = shelve.open(shelvefile, flag=shelve_mode, protocol=pickle.HIGHEST_PROTOCOL))
def close(self):
    self.shelve.close()
    fcntl.flock(self.lockfd.fileno(), LOCK_UN)
    lockfd.close()
对于任何感兴趣的人,我都是作为上下文管理器实现的:

from contextlib import contextmanager, closing
from fcntl import flock, LOCK_SH, LOCK_EX, LOCK_UN
import shelve

@contextmanager
def locking(lock_path, lock_mode):
    with open(lock_path, 'w') as lock:
        flock(lock.fileno(), lock_mode) # block until lock is acquired
        try:
            yield
        finally:
            flock(lock.fileno(), LOCK_UN) # release

class DBManager(object):
    def __init__(self, db_path):
        self.db_path = db_path

    def read(self):
        with locking("%s.lock" % self.db_path, LOCK_SH):
            with closing(shelve.open(self.db_path, "c", 2)) as db:
                return dict(db)

    def cas(self, old_db, new_db):
        with locking("%s.lock" % self.db_path, LOCK_EX):
            with closing(shelve.open(self.db_path, "c", 2)) as db:
                if old_db != dict(db):
                    return False
                db.clear()
                db.update(new_db)
                return True

顺便说一句,我想将比较和交换限制在特定的顶级密钥上,但我不确定更新密钥是否不会覆盖所有其他密钥,也可能取决于底层数据库,以便更好地锁定整个过程并确保安全