GNU/Linux >> Tutoriels Linux >  >> Linux

Mutex à l'échelle du système en Python sur Linux

Essayez la bibliothèque ilock :

from ilock import ILock

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

La réponse Unix "traditionnelle" consiste à utiliser des verrous de fichiers. Vous pouvez utiliser lockf(3) pour verrouiller des sections d'un fichier afin que d'autres processus ne puissent pas le modifier ; un abus très courant consiste à l'utiliser comme mutex entre les processus. L'équivalent python est fcntl.lockf.

Traditionnellement, vous écrivez le PID du processus de verrouillage dans le fichier de verrouillage, de sorte que les blocages dus à la mort des processus pendant le maintien du verrou soient identifiables et réparables.

Cela vous donne ce que vous voulez, puisque votre verrou se trouve dans un espace de noms global (le système de fichiers) et accessible à tous les processus. Cette approche a également l'avantage que des programmes non-Python peuvent participer à votre verrouillage. L'inconvénient est que vous avez besoin d'un emplacement pour ce fichier de verrouillage; de plus, certains systèmes de fichiers ne se verrouillent pas correctement, il y a donc un risque qu'il échoue silencieusement à réaliser l'exclusion. Vous en gagnez, vous en perdez.


Ma réponse chevauche les autres réponses, mais juste pour ajouter quelque chose que les gens peuvent copier-coller, je fais souvent quelque chose comme ça.

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

Et utilisez-le ensuite comme :

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

Pour tester, faites touch lockfile.lck puis exécutez le code ci-dessus dans deux ou plusieurs terminaux différents (à partir du même répertoire).

MISE À JOUR :smwikipedia a mentionné que ma solution est spécifique à Unix. J'avais besoin d'une version portable récemment et j'ai trouvé ce qui suit, avec l'idée d'un projet github aléatoire. Je ne suis pas sûr que les appels seek() soient nécessaires, mais ils sont là car l'API Windows verrouille une position spécifique dans le fichier. Si vous n'utilisez pas le fichier pour autre chose que le verrouillage, vous pouvez probablement supprimer les recherches.

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

La norme POSIX spécifie les sémaphores inter-processus qui peuvent être utilisés à cette fin. http://linux.die.net/man/7/sem_overview

Le multiprocessing module en Python est construit sur cette API et d'autres. En particulier, multiprocessing.Lock fournit un « mutex » inter-processus. http://docs.python.org/library/multiprocessing.html#synchronization-between-processes

MODIFIER pour répondre à la question modifiée :

Dans votre preuve de concept, chaque processus construit un Lock() . Vous avez donc deux serrures distinctes. C'est pourquoi aucun processus n'attend. Vous devrez partager le même verrou entre les processus. La section à laquelle j'ai lié dans le multiprocessing la documentation explique comment procéder.


Linux
  1. Comment installer Python sur Linux

  2. Comment installer Python 3.10 sur Rocky Linux 8

  3. Comment utiliser les exemples de verrouillage C Mutex pour la synchronisation des threads Linux

  4. Installer un programme Python sous Linux

  5. Mettre à jour python sur linux 2.7 à 3.5

Installer python 3 sur Redhat 8

bpython - Un interpréteur Python fantaisie pour Linux

Comment installer Dash Framework en Python sur Linux

Comment installer la bibliothèque Python PyBrain sous Linux

Comment installer Setuptools pour Python sur Linux

Comment installer Anaconda Python sur Rocky Linux 8