Llamando a un método varias veces con varios hilos.

Quiero que se encienda un LED, mientras se está trabajando en mi Raspberry. Estoy usando un Thread para el LED en mi script de Python.

El código inicial:

import RPi.GPIO import time import threading pinLED = 10 pinButton = 12 GPIO.setmode(GPIO.BOARD) GPIO.setup(pinLED, GPIO.OUT) GPIO.setup(pinButton, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) GPIO.output(pinLED, 0) 

Método para el hilo:

 working = False def flash(): status = 0 while working: time.sleep(0.5) if status == 0: GPIO.output(pinLED, 1) status = 1 else: GPIO.output(pinLED, 0) status = 0| GPIO.output(pinLED, 0) 

Lógica:

 try: while True: time.sleep(0.02) #found out that 0.02 is a good value to get every tiny button push and save resources if GPIO.input(pinButton) == 1: t = threading.Thread(target=flash) working = True t.start() time.sleep(5) #work would be here working = False t.join() except Exception as e: print(e) finally: GPIO.cleanup() 

Cuando comienzo el guión y presiono el botón la primera vez, todo funciona y el led parpadea. Pero cuando presiono el botón por segunda vez, sin reiniciar el script, el led no parpadea. Imprimí algunos mensajes de depuración y descubrí que se llama a t.start (), pero por alguna razón no hace nada, tampoco se lanza una excepción. ¿No debe comenzar a parpadear el LED cada vez que presiono el botón nuevamente?

Related of "Llamando a un método varias veces con varios hilos."

No encontré ningún fallo lógico y confirmo que funciona, pero usé los siguientes cambios:

  1. Iniciar el main_thread desde adentro if __name__ == '__main__':
    Sugiero mover también todas las llamadas GPIO dentro de este block .

Evite colocar el código que se ejecuta en el inicio fuera de if __name__ == '__main__':

De la documentación: Importación segura del módulo principal Uno debería proteger el “punto de entrada” del progtwig utilizando si __name__ == ‘__main__’:

  1. Se agregó join() después de working = False , esto garantizaba que el hilo había terminado antes de volver a iniciarlo.

     working = False t.join() 

Yo sugeriría cambiar el def flash() , a lo siguiente:
Usar threading.Event() lugar de una global Instance y pasarlo junto con el pinLED . Esto generaliza el def flash(...) y permite su uso con diferentes pinLED , incluso en paralelo. Defina el status como threading.local() threadsafe, por lo que los valores de la instancia serán diferentes para los hilos separados.
Por ejemplo:

 def flash(pinLED, flashing): status = threading.local() status.LED = False while flashing.is_set(): status.LED = not status.LED GPIO.output(pinLED, int(status.LED)) time.sleep(0.5) GPIO.output(pinLED, 0) 

Cambios en el main_thread :

 def main_thread(): flashing = threading.Event() flashing.clear() try: while True: time.sleep(0.02) if GPIO.input(pinButton) == 1: t = threading.Thread(target=flash, args=(pinLED, flashing,)) flashing.set() t.start() time.sleep(2) # work would be here flashing.clear() t.join() ... 

Probado con Python: 3.4.2