GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Systemweiter Mutex in Python unter Linux

Versuchen Sie es mit der ilock-Bibliothek:

from ilock import ILock

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

Die "traditionelle" Unix-Antwort besteht darin, Dateisperren zu verwenden. Sie können lockf(3) verwenden Abschnitte einer Datei zu sperren, damit andere Prozesse sie nicht bearbeiten können; Ein sehr häufiger Missbrauch ist die Verwendung als Mutex zwischen Prozessen. Das Python-Äquivalent ist fcntl.lockf.

Traditionell schreiben Sie die PID des Sperrprozesses in die Sperrdatei, damit Deadlocks aufgrund von Prozessen, die sterben, während die Sperre gehalten wird, identifizierbar und behebbar sind.

Damit erhalten Sie, was Sie wollen, da sich Ihre Sperre in einem globalen Namensraum (dem Dateisystem) befindet und für alle Prozesse zugänglich ist. Dieser Ansatz hat auch den Vorteil, dass Nicht-Python-Programme an Ihrer Sperrung teilnehmen können. Der Nachteil ist, dass Sie einen Platz brauchen, an dem diese Sperrdatei leben kann; Außerdem werden einige Dateisysteme nicht richtig gesperrt, sodass das Risiko besteht, dass der Ausschluss stillschweigend nicht erreicht wird. Du gewinnst einige, du verlierst einige.


Meine Antwort überschneidet sich mit den anderen Antworten, aber nur um etwas hinzuzufügen, das die Leute kopieren und einfügen können, mache ich oft so etwas.

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

Und dann verwenden Sie es als:

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

Führen Sie zum Testen touch lockfile.lck aus Führen Sie dann den obigen Code in zwei oder mehr verschiedenen Terminals aus (aus demselben Verzeichnis).

UPDATE:smwikipedia hat erwähnt, dass meine Lösung unixspezifisch ist. Ich brauchte kürzlich eine portable Version und kam mit der Idee aus einem zufälligen Github-Projekt auf Folgendes. Ich bin mir nicht sicher, ob die seek()-Aufrufe benötigt werden, aber sie sind da, weil die Windows-API eine bestimmte Position in der Datei sperrt. Wenn Sie die Datei für nichts anderes als zum Sperren verwenden, können Sie wahrscheinlich die Suchvorgänge entfernen.

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

Der POSIX-Standard spezifiziert prozessübergreifende Semaphore, die für diesen Zweck verwendet werden können. http://linux.die.net/man/7/sem_overview

Die multiprocessing Modul in Python basiert auf dieser API und anderen. Insbesondere multiprocessing.Lock bietet einen prozessübergreifenden "Mutex". http://docs.python.org/library/multiprocessing.html#synchronization-between-processes

BEARBEITEN um auf die bearbeitete Frage zu antworten:

In Ihrem Proof of Concept erstellt jeder Prozess einen Lock() . Sie haben also zwei separate Schlösser. Deshalb wartet keiner der Prozesse. Sie müssen die gleiche Sperre zwischen Prozessen teilen. Der Abschnitt, auf den ich im multiprocessing verlinkt habe Dokumentation erklärt, wie das geht.


Linux
  1. So installieren Sie Python unter Linux

  2. Python-any()-Funktion unter Linux

  3. So installieren Sie Python unter Linux Mint 20

  4. So verwenden Sie den Export mit Python unter Linux

  5. Systemweite globale Variable / Semaphor / Mutex in C++/Linux?

Installieren Sie Python 3 auf Redhat 8

bpython – Ein schicker Python-Interpreter für Linux

So installieren Sie Dash Framework in Python unter Linux

So installieren Sie die PyBrain-Python-Bibliothek unter Linux

So installieren Sie Setuptools für Python unter Linux

So installieren Sie Anaconda Python unter Rocky Linux 8