How to terminate thread with an infinite loop? [duplicate] - python

This question already has answers here:
Is there any way to kill a Thread?
(31 answers)
Closed 3 years ago.
To simplify the situation I'm having: I'm trying to terminate a thread while it is still running in Python 2.7, and I'm not sure how to do it.
Take this simple code:
import time
import threading
def thread1():
print "Starting thread 1"
while True:
time.sleep(0.5)
print "Working"
thread1 = threading.Thread(target=thread1, args=())
thread1.start()
time.sleep(2)
print "Killing thread 1"
thread2.stop()
print "Checking if it worked:"
print "Thread is: " + str(thread1.isAlive())
Thread 1 keeps on 'working' and I'm trying to kill it in the main thread. Any idea on how to do it? I've tried:
threat1.terminate
threat1.stop
threat1.quit
threat1.end
This all seems to point that there is no way to really stop it with a simple line of code. What could you suggest?

To terminate an Thread controlled, using a threadsafe threading.Event():
import threading, time
def Thread_Function(running):
while running.is_set():
print('running')
time.sleep(1)
if __name__ == '__main__':
running = threading.Event()
running.set()
thread = threading.Thread(target=Thread_Function, args=(running,))
thread.start()
time.sleep(1)
print('Event running.clear()')
running.clear()
print('Wait until Thread is terminating')
thread.join()
print("EXIT __main__")
Output:
running
running
Event running.clear()
Wait until Thread is terminating
EXIT __main__
Tested with Python:3.4.2
Online Demo: reply.it

Usually, in this cases, I use some kind of signal:
import time
import threading
class thread1(threading.Thread):
def run(self):
self.kill = False
print "Starting thread 1"
while not self.kill:
time.sleep(0.5)
print "Working"
thread_obj = thread1()
thread_obj.start()
time.sleep(2)
print "Killing thread 1"
thread_obj.kill = True
print "Checking if it worked:"
time.sleep(1)
print "Thread is: " + str(thread_obj.isAlive())
EDIT
After reading the answer suggested in one of the comment... I realized that this is just a simplified version of what is described there. I hope this will be useful anyway.

Indeed!
threads cannot be destroyed, stopped, suspended, resumed, or interrupted
(So say the docs in a paragraph below the link.)
Make your threads listen to signals you may send, via a queue (best), a shared variable (worse), or any other means. Be careful and don't let them run unchecked loops, as in your example code.

Related

os._exit() called on another thread does not exit a program

I just start a new thread:
self.thread = ThreadedFunc()
self.thread.start()
after something happens I want to exit my program so I'm calling os._exit():
os._exit(1)
The program still works. Everything is functional and it just looks like the os._exit() didn't execute.
Is there a different way to exit a whole program from different thread? How to fix this?
EDIT: Added more complete code sample.
self.thread = DownloadThread()
self.thread.data_downloaded.connect(self.on_data_ready)
self.thread.data_progress.connect(self.on_progress_ready)
self.progress_initialized = False
self.thread.start()
class DownloadThread(QtCore.QThread):
# downloading stuff etc.
sleep(1)
subprocess.call(os.getcwd() + "\\another_process.exe")
sleep(2)
os._exit(1)
EDIT 2: SOLVED! There is a quit(), terminate() or exit() function which just stops the thread. It was that easy. Just look at the docs.
Calling os._exit(1) works for me.
You should use the standard lib threading.
I guess you are using multiprocessing, which is a process-based “threading” interface, which uses similar API to threading, but creates child process instead of child thread. so os._exit(1) only exits child process, not affecting the main process
Also you should ensure you have called join() function in the main thread. Otherwise, it is possible that the operating system schedules to run the main thread to the end before starting to do anything in child thread.
sys.exit() does not work because it is the same as raising a SystemExit exception. Raising an exception in thread only exits that thread, rather than the entire process.
Sample code. Tested under ubuntu by python3 thread.py; echo $?.
Return code is 1 as expected
import os
import sys
import time
import threading
# Python Threading Example for Beginners
# First Method
def greet_them(people):
for person in people:
print("Hello Dear " + person + ". How are you?")
os._exit(1)
time.sleep(0.5)
# Second Method
def assign_id(people):
i = 1
for person in people:
print("Hey! {}, your id is {}.".format(person, i))
i += 1
time.sleep(0.5)
people = ['Richard', 'Dinesh', 'Elrich', 'Gilfoyle', 'Gevin']
t = time.time()
#Created the Threads
t1 = threading.Thread(target=greet_them, args=(people,))
t2 = threading.Thread(target=assign_id, args=(people,))
#Started the threads
t1.start()
t2.start()
#Joined the threads
t1.join() # Cannot remove this join() for this example
t2.join()
# Possible to reach here if join() removed
print("I took " + str(time.time() - t))
Credit: Sample code is copied and modified from https://www.simplifiedpython.net/python-threading-example/

Cannot Kill a process that has a thread started [duplicate]

This question already has answers here:
Daemon Threads Explanation
(9 answers)
Closed 3 years ago.
I have a python script that starts a process using multiprocessing Process class. Inside that process I start a thread with an infinite loop, and I simulate an exception on the main thread by doing exit(1). I was expecting exit to kill the process, but it doesn't, and the main thread reports it as alive.
I have tried with both raising exception and calling exit, but none work.
I have tried waiting for the process to finish by waiting for is_alive, and by calling join. But both have the same behavior.
from multiprocessing import Process
from threading import Thread
from time import sleep
def infinite_loop():
while True:
print("It's sleeping man")
sleep(1)
def start_infinite_thread():
run_thread = Thread(target=infinite_loop)
run_thread.start()
exit(1)
def test_multi():
x = Process(target=start_infinite_thread)
x.start()
sleep(5)
assert not x.is_alive()
I am expecting the process not to be alive, but the assert fails.
Thanks #Imperishable Night for the reply, by setting the thread as daemon the test passes.
Code that works:
from multiprocessing import Process
from threading import Thread
from time import sleep
def infinite_loop():
while True:
print("It's sleeping man")
sleep(1)
def start_infinite_thread():
run_thread = Thread(target=infinite_loop)
run_thread.daemon = True
run_thread.start()
exit(1)
def test_multi():
x = Process(target=start_infinite_thread)
x.start()
sleep(1)
assert not x.is_alive()

Python Paramiko Ctrl Z is not working for threading [duplicate]

I am testing Python threading with the following script:
import threading
class FirstThread (threading.Thread):
def run (self):
while True:
print 'first'
class SecondThread (threading.Thread):
def run (self):
while True:
print 'second'
FirstThread().start()
SecondThread().start()
This is running in Python 2.7 on Kubuntu 11.10. Ctrl+C will not kill it. I also tried adding a handler for system signals, but that did not help:
import signal
import sys
def signal_handler(signal, frame):
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
To kill the process I am killing it by PID after sending the program to the background with Ctrl+Z, which isn't being ignored. Why is Ctrl+C being ignored so persistently? How can I resolve this?
Ctrl+C terminates the main thread, but because your threads aren't in daemon mode, they keep running, and that keeps the process alive. We can make them daemons:
f = FirstThread()
f.daemon = True
f.start()
s = SecondThread()
s.daemon = True
s.start()
But then there's another problem - once the main thread has started your threads, there's nothing else for it to do. So it exits, and the threads are destroyed instantly. So let's keep the main thread alive:
import time
while True:
time.sleep(1)
Now it will keep print 'first' and 'second' until you hit Ctrl+C.
Edit: as commenters have pointed out, the daemon threads may not get a chance to clean up things like temporary files. If you need that, then catch the KeyboardInterrupt on the main thread and have it co-ordinate cleanup and shutdown. But in many cases, letting daemon threads die suddenly is probably good enough.
KeyboardInterrupt and signals are only seen by the process (ie the main thread)... Have a look at Ctrl-c i.e. KeyboardInterrupt to kill threads in python
I think it's best to call join() on your threads when you expect them to die. I've taken the liberty to make the change your loops to end (you can add whatever cleanup needs are required to there as well). The variable die is checked on each pass and when it's True, the program exits.
import threading
import time
class MyThread (threading.Thread):
die = False
def __init__(self, name):
threading.Thread.__init__(self)
self.name = name
def run (self):
while not self.die:
time.sleep(1)
print (self.name)
def join(self):
self.die = True
super().join()
if __name__ == '__main__':
f = MyThread('first')
f.start()
s = MyThread('second')
s.start()
try:
while True:
time.sleep(2)
except KeyboardInterrupt:
f.join()
s.join()
An improved version of #Thomas K's answer:
Defining an assistant function is_any_thread_alive() according to this gist, which can terminates the main() automatically.
Example codes:
import threading
def job1():
...
def job2():
...
def is_any_thread_alive(threads):
return True in [t.is_alive() for t in threads]
if __name__ == "__main__":
...
t1 = threading.Thread(target=job1,daemon=True)
t2 = threading.Thread(target=job2,daemon=True)
t1.start()
t2.start()
while is_any_thread_alive([t1,t2]):
time.sleep(0)
One simple 'gotcha' to beware of, are you sure CAPS LOCK isn't on?
I was running a Python script in the Thonny IDE on a Pi4. With CAPS LOCK on, Ctrl+Shift+C is passed to the keyboard buffer, not Ctrl+C.

More pythonic way to exit a python thread - daemon vs stop_event

The following code:
import threading
import time
from functools import partial
from itertools import count
def daemon_loop(sleep_interval, stop_event):
for j in count():
print(j)
if stop_event.is_set():
break
time.sleep(sleep_interval)
print('Slept %s' % sleep_interval)
print('Prod terminating')
if __name__ == '__main__':
stop_event = threading.Event() #https://stackoverflow.com/a/41139707/281545
target = partial(daemon_loop, sleep_interval=2, stop_event=stop_event)
prod_thread = threading.Thread(target=target,
# daemon=True
)
try:
prod_thread.start()
while True:
time.sleep(10)
except KeyboardInterrupt:
print('Terminating...')
stop_event.set()
prints on a keyboard interrupt:
C:\Users\MrD\.PyCharm2018.2\config\scratches>c:\_\Python363-64\python.exe thread_daemon.py
0
Slept 2
1
Terminating...
Slept 2
2
Prod terminating
Uncommenting the # daemon=True line results in the prod_thread being ended immediately:
C:\Users\MrD\.PyCharm2018.2\config\scratches>c:\_\Python363-64\python.exe thread_daemon.py
0
Slept 2
1
Terminating...
My question is what is the preferred/more pythonic way to deal with thread termination - should I drop the Event machinery and just mark the thread as daemon or is there some edge case I miss?
See:
Daemon Threads Explanation
How to stop daemon thread?
I haven't done enough Python to give you a "Pythonic" answer, but I can answer in more general programming terms.
Firstly, I'm not a fan of terminating threads. There are cases where it is safe and OK, such as your example here - but terminating in the middle of print writing its output would feel a little dirty.
Secondly, if you want to continue using sleep (which I'm also not a fan of) you could repeat your if stop_event.is_set(): and break after the sleep. (Don't move the code, copy it.) The main problem with sleep in this case is that it will wait the full sleep_interval even if the event is set during that time.
Thirdly - and my preference - instead of using sleep, do a wait on the event with a timeout. If the event is not set during the wait, wait returns false after waiting the timeout period. If the event is set before or during the wait, wait returns true immediately (that is, it aborts the timeout, giving you fast, clean shutdown of the thread.)
So your code would look something like this:
def daemon_loop(sleep_interval, stop_event):
for j in count():
print(j)
if stop_event.wait(sleep_interval):
break
print('Slept %s' % sleep_interval)
print('Prod terminating')

what is best way to implement thread maximum execution time (in python/gtk)?

What is the best known practice to implement a thread job timeout (ie: kill the job after a maximum of X seconds) ?
I wrote the following python code. I read a lot of different way to implement this but I'm a little lost... Do I have to do this with a timer ? or by counting in add_timeout callback ?
as a side note , usage of thread.join(timeout) is pretty limited within gtk/threaded application as it blocks the main thread ?
Thanks !!
Note: I'm pretty new to python/threading
#!/usr/bin/python
import time
import threading
import gobject
import gtk
import glib
gobject.threads_init()
class myui():
def __init__(self):
interface = gtk.Builder()
interface.add_from_file("myui.glade")
interface.connect_signals(self)
self.spinner = interface.get_object('spinner1')
def bg_work1(self):
print "work has started"
# simulates some work
time.sleep(5)
print "work has finished"
def startup(self):
thread = threading.Thread(target=self.bg_work1)
thread.start()
# work started. Now while the work is being done I want
# a spinner to rotate
self.spinner.start()
print "spinner started"
#thread.join() # I wanna wait for the job to be finished while the spinner spins.
# but this seems to block the main thread, and so the gui doesn't shows up !
glib.timeout_add(100, self.check_job, thread, 5)
def check_job(self, thread, timeout):
#print 'check job called'
if not thread.isAlive():
print 'is not alive anymore'
self.spinner.stop()
return False
return True
if __name__ == "__main__":
app = myui()
app.startup()
print "gtk main loop starting !"
gtk.main()
print "gtk main loop has stopped !"
Your code seems pretty good, the only thing missing is to use and evaluate a timeout point:
glib.timeout_add(100, self.check_job, thread, time.time() + 5)
def check_job(self, thread, timeout):
#print 'check job called'
if not thread.isAlive():
print 'is not alive anymore'
self.spinner.stop()
return False
if time.time() > timeout:
print 'job timed out'
self.spinner.stop()
return False
return True
However, this does not kill your worker thread after the timeout, so it will still be running. I am not aware of a method to forcibly terminate a Python thread. You would have to split your work and check for timeout in the worker thread, so it can gracefully terminate.

Categories

Resources