Frage

Hat ad acta das Python-Modul irgendwelche eingebauten Schutz sicher zwei Prozesse machen schreiben nicht in eine Datei zur gleichen Zeit?

War es hilfreich?

Lösung

Das shelve Modul verwendet ein zugrunde liegendes Datenbankpaket (wie dbm, gdbm oder bsddb).

Die Einschränkungen pragraph sagt (mein Schwerpunkt):

  

Der shelve Modul nicht unterstützt gleichzeitigen Lese- / Schreibzugriff auf Eis gelegt Objekte . (Mehrere gleichzeitigen Lesezugriffe sicher sind.) Wenn ein Programm ein Regal zum Schreiben geöffnet hat, sollte kein anderes Programm es zum Lesen oder Schreiben geöffnet haben. Unix-Dateisperren können verwendet werden, um dies zu lösen, aber dies unterscheidet über Unix-Versionen und erfordert Kenntnisse über die Datenbank-Implementierung verwendet.

Fazit: es hängt von O und die zugrunde liegenden DB. Um die Dinge tragbar, baut nicht auf Gleichzeitigkeit.

Andere Tipps

Gemäß der Top-Antwort, ist es nicht sicher mehrere Autoren an die shelve zu haben. Meine Methode, um die Regale sicherer ist ein Wrapper zu schreiben, die Pflege der Öffnung nimmt und den Zugriff auf Elemente ad acta legen. Der Wrapper-Code sieht etwa so aus:

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()

Ich habe implementiert Ivo Ansatz als Kontext-Manager, für jedermann Interesse:

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top