题
是否Python的搁置模块内置有任何保护措施,以确保两个进程没有同时写入文件?
解决方案
在货架模块使用底层数据库包(如DBM, GDBM 或bsddb)。
在的限制的pragraph 说(我强调):
在货架模块的不支持搁置对象强>并行读/写访问。 (多个同时读访问是安全的。)当一个程序具有对写开放的架子,没有其他的程序应该有它打开读取或写入。 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
不隶属于 StackOverflow