Consulta si los hilos de Python. El locking está bloqueado o no

Tengo un subproceso que estoy ejecutando (código a continuación) que inicia un subproceso de locking. Para garantizar que otros subprocesos no inicien el mismo subproceso, tengo un locking alrededor de esta llamada subprocess.call . También quiero poder terminar esta llamada de subproceso, así que tengo una función de parada a la que llamo desde otro lugar. En el caso de que el subproceso se detenga prematuramente, también quiero liberar el locking, que es lo que hace el siguiente código:

 class SomeThread(threading.Thread): def run(self): aLock.acquire() self.clip = subprocess.call([ 'mplayer', 'Avatar.h264'], stdin=subprocess.PIPE) aLock.release() def stop(self): if self.clip != None and self.clip.poll() == True: try: self.clip.send_signal(signal.SIGINT) except: pass aLock.release() 

Sin embargo, de acuerdo con la documentación aquí , llamar a release() en un locking liberado generará una excepción:

 A RuntimeError is raised if this method is called when the lock is unlocked. 

¿Existe una función de consulta como aLock.isLocked() ?

¡Por supuesto!

 >>> from threading import Lock >>> x = Lock() >>> x.locked() False >>> x.acquire() True >>> x.locked() True 

También puedes hacer una adquisición no bloqueante:

 x.acquire(False) x.release() 

En ese caso, si x fue desbloqueado, el código lo adquiere y lo libera. Pero si x ya estaba bloqueado, la adquisición sin locking devuelve al mismo tiempo (y devuelve False ), y nuevamente lo liberamos. ¡Pero eso está sujeto a las carreras! No hay nada que impida que otro hilo suelte el locking entre esas dos líneas.

Lo mismo para comprobar .locked() . Eso solo le indica el estado del locking en el momento en que se ejecutó .locked() . Puede que ya no sea cierto para cuando ejecute la siguiente instrucción.

Por cierto, el cuerpo de run() se escribe mejor usando el locking como un “administrador de contexto”, así:

 def run(self): with aLock: self.clip = subprocess.call([ 'mplayer', 'Avatar.h264'], stdin=subprocess.PIPE) 

Hace el par de acquire()/release() para usted, y es mucho más robusto contra las excepciones inesperadas generadas en el cuerpo del bloque with (Python hace todo lo posible para liberar el locking si se sale del cuerpo por cualquier motivo).