GNU/Linux >> Linux Esercitazione >  >> Linux

Mutex a livello di sistema in Python su Linux

Prova la libreria ilock:

from ilock import ILock

with ILock('Unique lock name'):
    # The code should be run as a system-wide single instance
    ...

La risposta Unix "tradizionale" è usare i blocchi dei file. Puoi usare lockf(3) bloccare sezioni di un file in modo che altri processi non possano modificarlo; un abuso molto comune è usarlo come mutex tra i processi. L'equivalente di Python è fcntl.lockf.

Tradizionalmente si scrive il PID del processo di blocco nel file di blocco, in modo che i deadlock dovuti a processi che muoiono mentre si mantiene il blocco siano identificabili e risolvibili.

Questo ti dà quello che vuoi, dal momento che il tuo blocco è in uno spazio dei nomi globale (il filesystem) e accessibile a tutti i processi. Questo approccio ha anche il vantaggio che i programmi non Python possono partecipare al tuo blocco. Lo svantaggio è che hai bisogno di un posto dove vivere questo file di blocco; inoltre, alcuni filesystem in realtà non si bloccano correttamente, quindi c'è il rischio che non riesca silenziosamente a ottenere l'esclusione. Ne vinci un po', ne perdi un po'.


La mia risposta si sovrappone alle altre risposte, ma solo per aggiungere qualcosa che le persone possono copiare e incollare, spesso faccio qualcosa del genere.

class Locker:
    def __enter__ (self):
        self.fp = open("./lockfile.lck")
        fcntl.flock(self.fp.fileno(), fcntl.LOCK_EX)

    def __exit__ (self, _type, value, tb):
        fcntl.flock(self.fp.fileno(), fcntl.LOCK_UN)
        self.fp.close()

E poi usalo come:

print("waiting for lock")
with Locker():
    print("obtained lock")
    time.sleep(5.0)

Per testare, esegui touch lockfile.lck quindi eseguire il codice precedente in due o più terminali diversi (dalla stessa directory).

AGGIORNAMENTO:smwikipedia ha menzionato che la mia soluzione è specifica per Unix. Di recente avevo bisogno di una versione portatile e mi è venuta in mente quanto segue, con l'idea di un progetto github casuale. Non sono sicuro che le chiamate seek() siano necessarie ma sono presenti perché l'API di Windows blocca una posizione specifica nel file. Se non stai usando il file per qualcosa di diverso dal blocco, probabilmente puoi rimuovere le ricerche.

if os.name == "nt":
    import msvcrt

    def portable_lock(fp):
        fp.seek(0)
        msvcrt.locking(fp.fileno(), msvcrt.LK_LOCK, 1)

    def portable_unlock(fp):
        fp.seek(0)
        msvcrt.locking(fp.fileno(), msvcrt.LK_UNLCK, 1)
else:
    import fcntl

    def portable_lock(fp):
        fcntl.flock(fp.fileno(), fcntl.LOCK_EX)

    def portable_unlock(fp):
        fcntl.flock(fp.fileno(), fcntl.LOCK_UN)


class Locker:
    def __enter__(self):
        self.fp = open("./lockfile.lck")
        portable_lock(self.fp)

    def __exit__(self, _type, value, tb):
        portable_unlock(self.fp)
        self.fp.close()

Lo standard POSIX specifica i semafori tra processi che possono essere utilizzati per questo scopo. http://linux.die.net/man/7/sem_overview

Il multiprocessing Il modulo in Python è costruito su questa API e altri. In particolare, multiprocessing.Lock fornisce un "mutex" cross-process. http://docs.python.org/library/multiprocessing.html#synchronization-between-processes

MODIFICA per rispondere alla domanda modificata:

Nella tua prova di concetto ogni processo sta costruendo un Lock() . Quindi hai due serrature separate. Ecco perché nessuno dei due processi attende. Dovrai condividere lo stesso blocco tra i processi. La sezione a cui mi sono collegato nel multiprocessing la documentazione spiega come farlo.


Linux
  1. Installa Python su Rocky Linux 8

  2. Linux:monitoraggio a livello di sistema delle chiamate a una funzione di libreria?

  3. Come utilizzare gli esempi di blocco Mutex C per la sincronizzazione dei thread di Linux

  4. Come utilizzare l'esportazione con Python su Linux

  5. Variabile globale a livello di sistema / semaforo / mutex in C++/Linux?

Installa Python 3 su Redhat 8

bpython – Un fantastico interprete Python per Linux

Come installare Dash Framework in Python su Linux

Come installare la libreria Python PyBrain in Linux

Come installare Setuptools per Python su Linux

Come installare Anaconda Python su Rocky Linux 8