GNU/Linux >> Znalost Linux >  >> Linux

Systémový mutex v Pythonu na Linuxu

Zkuste knihovnu ilock:

from ilock import ILock

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

"Tradiční" unixovou odpovědí je použití zámků souborů. Můžete použít lockf(3) zamknout části souboru, aby je ostatní procesy nemohly upravovat; velmi častým zneužitím je používat toto jako mutex mezi procesy. Ekvivalent pythonu je fcntl.lockf.

Tradičně zapisujete PID zamykacího procesu do souboru zámku, takže zablokování způsobené procesy odumírajícími při držení zámku jsou identifikovatelné a opravitelné.

Tím získáte, co chcete, protože váš zámek je v globálním jmenném prostoru (systém souborů) a je přístupný všem procesům. Tento přístup má také tu výhodu, že se na vašem zamykání mohou podílet i jiné programy než Python. Nevýhodou je, že pro tento soubor zámku potřebujete místo k životu; některé souborové systémy se také ve skutečnosti nezamykají správně, takže existuje riziko, že se tiše nepodaří dosáhnout vyloučení. Něco vyhrajete, něco prohrajete.


Moje odpověď se překrývá s ostatními odpověďmi, ale jen abych přidal něco, co mohou lidé zkopírovat a vložit, často dělám něco takového.

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

A pak jej použijte jako:

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

Chcete-li otestovat, proveďte touch lockfile.lck poté spusťte výše uvedený kód ve dvou nebo více různých terminálech (ze stejného adresáře).

AKTUALIZACE:smwikipedia zmínila, že mé řešení je specifické pro unix. Nedávno jsem potřeboval přenosnou verzi a přišel jsem s následujícím nápadem z náhodného projektu github. Nejsem si jistý, zda jsou volání seek() potřeba, ale jsou tam, protože Windows API zamyká konkrétní pozici v souboru. Pokud soubor nepoužíváte k ničemu jinému než k zamykání, pravděpodobně můžete hledání odstranit.

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

Standard POSIX specifikuje meziprocesové semafory, které lze pro tento účel použít. http://linux.die.net/man/7/sem_overview

multiprocessing modul v Pythonu je postaven na tomto API a dalších. Konkrétně multiprocessing.Lock poskytuje křížový proces "mutex". http://docs.python.org/library/multiprocessing.html#synchronization-between-processes

UPRAVIT pro odpověď na upravenou otázku:

Ve vašem proof of concept každý proces vytváří Lock() . Máte tedy dva samostatné zámky. Proto ani jeden proces nečeká. Budete muset sdílet stejný zámek mezi procesy. Sekce, na kterou jsem odkazoval v multiprocessing dokumentace vysvětluje, jak to udělat.


Linux
  1. Jak nainstalovat Python na Linux

  2. Funkce Python any() v Linuxu

  3. Jak nainstalovat Python na Linux Mint 20

  1. Nainstalujte Python na Rocky Linux 8

  2. Linux – celosystémové monitorování volání do funkce knihovny?

  3. Jak používat příklady zámku C Mutex pro synchronizaci vláken v Linuxu

  1. Jak používat export s Pythonem na Linuxu

  2. Instalace programu Python na Linux

  3. Jak spustit soubor python v linuxu