문제

Python Shelve 모듈에는 두 프로세스가 파일에 동시에 쓰지 않도록 보호 기능이 있습니까?

도움이 되었습니까?

해결책

Shelve 모듈은 기본 데이터베이스 패키지 (예 : DBM, GDBM 또는 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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top