GNU/Linux >> Tutoriales Linux >  >> Linux

Mutex de todo el sistema en Python en Linux

Pruebe la biblioteca ilock:

from ilock import ILock

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

La respuesta "tradicional" de Unix es usar bloqueos de archivos. Puedes usar lockf(3) para bloquear secciones de un archivo para que otros procesos no puedan editarlo; un abuso muy común es usar esto como un mutex entre procesos. El equivalente de Python es fcntl.lockf.

Tradicionalmente, escribe el PID del proceso de bloqueo en el archivo de bloqueo, de modo que los puntos muertos debidos a que los procesos mueren mientras se mantiene el bloqueo son identificables y reparables.

Esto le da lo que quiere, ya que su bloqueo está en un espacio de nombres global (el sistema de archivos) y accesible para todos los procesos. Este enfoque también tiene la ventaja de que los programas que no son de Python pueden participar en su bloqueo. La desventaja es que necesita un lugar para que viva este archivo de bloqueo; Además, algunos sistemas de archivos en realidad no se bloquean correctamente, por lo que existe el riesgo de que falle silenciosamente en lograr la exclusión. Ganas algo, pierdes algo.


Mi respuesta se superpone con las otras respuestas, pero solo para agregar algo que la gente pueda copiar y pegar, a menudo hago algo como esto.

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

Y luego úsalo como:

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

Para probar, haz touch lockfile.lck luego ejecute el código anterior en dos o más terminales diferentes (desde el mismo directorio).

ACTUALIZACIÓN:smwikipedia mencionó que mi solución es específica de Unix. Necesitaba una versión portátil recientemente y se me ocurrió lo siguiente, con la idea de un proyecto aleatorio de github. No estoy seguro de que se necesiten las llamadas a seek(), pero están ahí porque la API de Windows bloquea una posición específica en el archivo. Si no está utilizando el archivo para otra cosa que no sea el bloqueo, probablemente pueda eliminar las búsquedas.

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

El estándar POSIX especifica semáforos entre procesos que pueden usarse para este propósito. http://linux.die.net/man/7/sem_overview

El multiprocessing El módulo en Python se basa en esta API y otras. En particular, multiprocessing.Lock proporciona un "mutex" entre procesos. http://docs.python.org/library/multiprocessing.html#synchronization- between-processes

EDITAR para responder a la pregunta editada:

En su prueba de concepto, cada proceso está construyendo un Lock() . Entonces tienes dos cerraduras separadas. Es por eso que ningún proceso espera. Deberá compartir el mismo bloqueo entre procesos. La sección a la que me vinculé en el multiprocessing la documentación explica cómo hacerlo.


Linux
  1. Cómo instalar Python en Linux

  2. Función Python any () en Linux

  3. Instalar Python en Rocky Linux 8

  4. Cómo usar ejemplos de bloqueo C Mutex para la sincronización de subprocesos de Linux

  5. Cómo usar la exportación con Python en Linux

Instalar python 3 en Redhat 8

bpython:un intérprete sofisticado de Python para Linux

Cómo instalar Dash Framework en Python en Linux

Cómo instalar la biblioteca Python de PyBrain en Linux

Cómo instalar Setuptools para Python en Linux

Cómo instalar Anaconda Python en Rocky Linux 8