In python 2.7 it is very problematic. The Ctrl-C sends a signal that is only sent to the main thread. You would have to install a signal handler ( signal()
) in that thread, capture it, and put some Boolean global variable that the other threads consult periodically to know that they should end. In Python 3 the signal is instead sent to all threads, and handled by default by the interpreter, so that pressing Ctlr-C twice, kills all threads.
In any case, even in Python3, the reasonable thing is not to kill a thread "without more", because it could be in the middle of some important operation, but to signal it to finish when it can, by means of some global variable.
Example
Here is an example that uses the technique described. I have implemented the functions netstatCapture
and tasklistCapture
as infinite loops that contain a time.sleep()
. Your functions should also periodically call time.sleep()
, since this is an interruptible function that will "wake up" before Ctrl-C. In any case, the loop is not infinite at all, but it looks up the global variable terminar
to decide when to end.
This global variable is written from the appropriate signal handler, which is registered in the main program by signal.signal()
.
Note that the main thread must be kept "alive", because in Python 2 it is the only one that will receive the Ctrl-C signal and if this thread were to die, the signal would be lost and the whole scheme would fail. To keep him alive, I put him in another waiting loop, like the other threads:
# coding: utf-8
import threading
import time
import signal
terminar = False
def procesarCtrlC(*args):
"""Manejador para la señal SIGINT"""
global terminar
terminar = True
print("Detectado Ctrl-C con parametros {}".format(args))
def netstatCapture():
print("Arrancando netstatCapture")
while not terminar:
time.sleep(2)
print("Terminando netstatCapture")
def tasklistCapture():
print("Arrancando tasklistCapture")
while not terminar:
time.sleep(2)
print("Terminando tasklistCapture")
def runThreads():
"""
Creates and runs threads.
"""
t1 = threading.Thread(target=netstatCapture, name='netstatCapture')
t2 = threading.Thread(target=tasklistCapture, name='tasklistCapture')
t1.daemon = True
t1.start()
t2.daemon = True
t2.start()
def main():
print("Función principal")
runThreads()
print("Hios lanzados")
while not terminar:
time.sleep(4)
print("Terminando main")
if __name__ == '__main__':
# La siguiente línea "instala" el manejador de señal
signal.signal(signal.SIGINT, procesarCtrlC)
main = threading.Thread(target=main, name='main_function')
main.start()
while not terminar:
time.sleep(3)
This solution will also work in Python 3, although in the case of Python 3 a Ctrl-C would also work without the need to program anything special, although that would kill the threads at any time, whereas the previous approach only ends the threads when they re-iterate in their while()
and discover the termination condition, which is usually preferable because they have the opportunity to release resources, etc.