A similar question is "How do you kill a thread?"
You create an exit handler in your thread that is controlled by a lock or event object from the threading module. You then simply remove the lock or signal the event object. This informs the thread it should stop processing and exit gracefully. After signaling the thread in your main program, the only thing left to do is to use the thread.join() method in main which will wait for the thread to shut down.
A short example:
import threading
import time
def timed_output(name, delay, run_event):
while run_event.is_set():
time.sleep(delay)
print name,": New Message!"
def main():
run_event = threading.Event()
run_event.set()
d1 = 1
t1 = threading.Thread(target = timed_output, args = ("bob",d1,run_event))
d2 = 2
t2 = threading.Thread(target = timed_output, args = ("paul",d2,run_event))
t1.start()
time.sleep(.5)
t2.start()
try:
while 1:
time.sleep(.1)
except KeyboardInterrupt:
print "attempting to close threads. Max wait =",max(d1,d2)
run_event.clear()
t1.join()
t2.join()
print "threads successfully closed"
if __name__ == '__main__':
main()
If you REALLY need the functionality of killing a thread, use multiprocessing. It allows you to send SIGTERMs to individual "processes" (it's also very similar to the threading module). Generally speaking, threading is for when you are IO-bound, and multiprocessing is for when you are truly processor-bound.
Answer from Paul Seeb on Stack OverflowA similar question is "How do you kill a thread?"
You create an exit handler in your thread that is controlled by a lock or event object from the threading module. You then simply remove the lock or signal the event object. This informs the thread it should stop processing and exit gracefully. After signaling the thread in your main program, the only thing left to do is to use the thread.join() method in main which will wait for the thread to shut down.
A short example:
import threading
import time
def timed_output(name, delay, run_event):
while run_event.is_set():
time.sleep(delay)
print name,": New Message!"
def main():
run_event = threading.Event()
run_event.set()
d1 = 1
t1 = threading.Thread(target = timed_output, args = ("bob",d1,run_event))
d2 = 2
t2 = threading.Thread(target = timed_output, args = ("paul",d2,run_event))
t1.start()
time.sleep(.5)
t2.start()
try:
while 1:
time.sleep(.1)
except KeyboardInterrupt:
print "attempting to close threads. Max wait =",max(d1,d2)
run_event.clear()
t1.join()
t2.join()
print "threads successfully closed"
if __name__ == '__main__':
main()
If you REALLY need the functionality of killing a thread, use multiprocessing. It allows you to send SIGTERMs to individual "processes" (it's also very similar to the threading module). Generally speaking, threading is for when you are IO-bound, and multiprocessing is for when you are truly processor-bound.
There are a couple of options that don't require using locks or other signals between threads. One is setting the threads as daemons, which will be killed off automatically when the main thread exits. The other is using processes instead, which have a terminate method you can call from the main process, if you needed to kill them and keep the main program running.
Both of these are especially useful if you have threads blocking on input. While using a timeout and periodically checking the signal would work in most cases without too much overhead, using daemons or processes eliminates the need for any busy loops or significant added complexity.
See the answers to this question for more details on these solutions and discussion on the problem of killing threads.
I didn't have this issue with multiprocessing module, or rather I did but forgot how I solved.
I am debugging and need to keyboard interrupt alot (plus it will always be required sporadically in future) and the console just hangs and I have to exit out of gnu screen and kill the pythong script manually.
I read an SO answer saying you simply have to put thread.join() in the keyboard interrupt exception but that didn't do anything!
try:
t = Thread(target=post_vid, args=(s, data))
t.start() # start the thread and continue
while t.is_alive():
print(vid_progress(s, vid_id))
except KeyboardInterrupt:
t.join()
I want it to stop immediately when I C-c or quite promptly at least.
python - threading ignores KeyboardInterrupt exception - Stack Overflow
KeyboardInterrupt behavior with multiple threads
I can't get threaded running of modules to exit from a keyboard interrupt
I found myself running into this problem when I was writing some code to sniff packets (for penetration testing). I never figured out a good way to solve it, as most of this is over my head. I stumbled across many links and articles trying to work around this problem. This stack overflow link has some good info. Hope it helps you.
More on reddit.commultithreading - Python - Can't kill main thread with KeyboardInterrupt - Stack Overflow
Try
try:
thread = reqthread()
thread.daemon = True
thread.start()
while True:
time.sleep(100)
except (KeyboardInterrupt, SystemExit):
print('Received keyboard interrupt, quitting threads.')
Without the call to time.sleep, the main process is jumping out of the try...except block too early, so the KeyboardInterrupt is not caught. My first thought was to use thread.join, but that seems to block the main process (ignoring KeyboardInterrupt) until the thread is finished.
thread.daemon=True causes the thread to terminate when the main process ends.
To summarize the changes recommended in the comments, the following works well for me:
try:
thread = reqthread()
thread.start()
while thread.isAlive():
thread.join(1) # not sure if there is an appreciable cost to this.
except (KeyboardInterrupt, SystemExit):
print '\n! Received keyboard interrupt, quitting threads.\n'
sys.exit()
This is my pseudo code.
./program.py --sources module_one,module_two
class ModuleRunner:
def run_module(self, sources):
results = {}
sources = sources.split(',')
sources_modules = {
'module_one': one.One(),
'module_two': two.Two()
}
threads = []
try:
for source in sources:
t = threading.Thread(target=lambda: results.update(sources_modules[source].run()))
threads.append(t)
t.start()
for t in threads:
t.join()
except KeyboardInterrupt:
print("thread interrupted")
sys.exit()
return results
Class One:
def run()
results = {}
try:
for i in range(1, 5)
url = f"https://example.com/?search={i}"
response = requests.get(url)
results.update(response)
except KeyboardInterrupt:
print("loop interrupted")
sys.exit()
return resultsThis is definitely going through the full range of the loop despite pressing ctrl+c, after which it will print "thread interrupted" to the screen, but more than that it will freeze the entire terminal and I have to open a new one to try the program again. I just want a keyboard interrupt to kill everything and exit immediately.
I found myself running into this problem when I was writing some code to sniff packets (for penetration testing). I never figured out a good way to solve it, as most of this is over my head. I stumbled across many links and articles trying to work around this problem. This stack overflow link has some good info. Hope it helps you.
The problem is that sys.exit will only exit your main thread: the other threads are still alive and won't receive the interrupt.
The clean way to do this is to have a shutdown mechanism in your main thread that communicates the other threads should stop. Eg. have them regularly poll an event and shutdown when it's signalled - when your main thread finishes, it signals that event then calls join on the threads.
A dirtier way is to mark those threads as daemon threads (by passing daemon=Trueto theThread` constructor), which indicates they should be killed when all non-daemon threads finish. The downside here is that if they're in the middle of something (eg. half-way through writing a file etc), it'll just die with no cleanup being done.
You made your threads daemons already, but you need to keep your main thread alive while daemon threads are there, there's how to do that: Cannot kill Python script with Ctrl-C
When you create the threads add them to a list of running threads and when dealing with ctrl-C send a kill signal to each thread on the list. That way you are actively cleaning up rather than relying on it being done for you.
If I have a while loop, lest say this one:
while True:
print("a")
time.sleep(3)
if keyboard.is_pressed('q'):
breakThe code only stops when I press 'q' after the previous code is finished. Is there a way to modify the loop so that it can be instantly interrupted regardless of which part of the code is being executed? I want the loop to break immediately upon pressing 'q' without waiting for the sleep period to finish.
Thanks in advance!