¿Debo usar eventos, semáforos, bloqueos, condiciones o una combinación de los mismos para administrar la salida segura de mi programa Python multiproceso?

Estoy escribiendo un programa de Python multiproceso en el que el subproceso principal y los otros subprocesos que genera se ejecutan como demonios (pero no con Thread.daemon = True) que buscan ciertos archivos en ciertos directorios y realizan acciones con ellos cuando existen. Es posible que se produzca un error en uno / cualquiera de los subprocesos que requeriría la salida de todo el programa. Sin embargo, necesito los otros hilos para terminar su trabajo actual antes de salir.

De lo que entiendo, si configuro myThread.daemon = True para mis hilos generados, saldrán automáticamente inmediatamente cuando salga el hilo principal. Sin embargo, quiero que los otros subprocesos terminen su trabajo actual antes de salir (a menos que el error sea algún tipo de falla catastrófica, en cuyo caso probablemente salga de todo de todos modos, de forma segura o no). Por lo tanto, no estoy configurando la propiedad daemon en True para los subprocesos.

Mirando la documentación del módulo de subprocesos y los diversos objetos disponibles para mí, como Eventos, Semáforos, Condiciones y Cerraduras, no estoy seguro de la mejor manera de manejar mi situación. Además, no estoy seguro de cómo manejar este escenario cuando el programa necesita terminar debido a señales SIGTERM / SIGINT.

Algún código que ilustra una versión simplificada de la estructura de mi programa:

import threading
import signals
import glob
import time

class MyThread1( threading.thread ):
    def __init__( self, name='MyThread1' ):
        threading.Thread.__init__( self )
        self.name = name
        return
    def run( self ):
        while True:
            filePathList = glob.glob( thisThreadDir + '/*.txt' )
            for file in filePathList:
                try:
                    doSomeProcessing( file )
                    # Then move the file to another thread's dir
                    # or potentially create a new file that will 
                    # be picked up by another thread
                except:
                    # Need to potentially tell all other threads
                    # to finish task and exit depending on error

            # I assume this would be the place to check for some kind of
            # flag or other indication to terminate the thread?
            time.sleep( 30 )


# Now imagine a few more custom threads with the same basic structure, 
# except that what is happening in doSomeProcessing() will obviously vary

# Main Thread/Script
def sigintHandler( SIGINT, frame ):
    # How do I handle telling all threads to finish their current loop
    # and then exit safely when I encounter this signal?
    sys.exit( 1 )

def sigtermHandler( SIGTERM, frame ):
    # Same question for this signal handler
    sys.exit( 1 )

signal.signal( signal.SIGINT, sigintHandler )
signal.signal( signal.SIGTERM, sigtermHandler )

myOtherThread1 = MyThread1()
myOtherThreadN = MyThreadN()

myOtherThread1.start()
myOtherThreadN.start()

while True:
    filePathList = glob.glob( mainDir + '/*.txt' )
    for file in filePathList:
        try:
            doMainProcessing( file )
            # Move file or write a new one in another thread's dir
        except:
            # Again, potentially need to exit the whole program, but want 
            # the other threads to finish their current loop first 

    # Check if another thread told us we need to exit?
    time.sleep( 30 )

Respuestas a la pregunta(1)

Su respuesta a la pregunta