When I run a While True loop in thread and use time.sleep() function the loop stops looping.
I am using this code:
import threading
from time import sleep
class drive_worker(threading.Thread):
def __init__(self):
super(drive_worker, self).__init__()
self.daemon = True
self.start()
def run(self):
while True:
print('loop')
#some code
time.sleep(0.5)
To start the thread I am using this code:
thread = drive_worker()
The loop stops because you flagged the thread as daemon.
The program terminates when there are only daemon threads left running.
self.daemon = True # remove this statement and the code should work as expected
Or make the main thread wait for the the daemon thread to finish
dthread = drive_worker()
# no call to start method since your constructor does that
dthread.join() #now the main thread waits for the new thread to finish
You imported sleep as
from time import sleep
so you have to call sleep in run() as sleep(0.5) or you have to change import as
import time
which I do not recommend.
Related
It is general in programming in Python that when I have a function or something which when I call, it blocks my code to proceed. So I think the best way to unblock is using threads but If I need to stop a thread what should I do?
I tried this reference and I wrote this simple program:
import threading
from time import sleep
class my_thread(threading.Thread):
"""Thread class with a stop() method. The thread itself has to check
regularly for the stopped() condition."""
def __init__(self):
super(my_thread, self).__init__()
self._stop_event = threading.Event()
def stop(self):
print("stopping the thread")
self._stop_event.set()
def stopped(self):
value=self._stop_event.is_set()
print("value of stop event is",value)
return value
def run(self):
print("running the thread")
print("start function startt()")
self.startt()
def startt(self):
print("it is going to wait forever")
while True:
#wait forever
pass
print("This line never execute")
def main():
for i in range(0,3):
print("it is the main function")
sleep(1)
if __name__+'__main__':
thr=my_thread()
thr.start()
sleep(5)
thr.stop()
thr.stopped()
print("calling the main function")
main()
print("Exiting the whole program")
My problem is this program actually stop the thread but after printing the last line the program still runs. What I want is if I call the stop function thr.start() it starts the thread and run #wait forever line and if I call the stop function thr.stop() it stop the whole class and returns from #wait forever line to the main function.
EDIT--
As #a_guest answer I can fix it but my problem is general for example If I had this code instead of while True:
pythoncom.PumpMessages()
(or any other code)
what should I do?
Instead of
while True:
...
you should use
while not self.stopped():
...
Then it will break out of the while loop once you stop() the thread.
You can't "abort" a running thread so to stop it you'll have to have a mechanism in the thread itself that periodically checks if it should stop.
Regular threads keep running while the rest of your program (process) exits.
If you make your thread a 'daemon' thread however, it will get killed automatically when your program exits. To do that, set self.daemon=True in your thread's init method. More info https://docs.python.org/3/library/threading.html#threading.Thread.daemon
I have the following two threads:
myThread = threading.Thread(target=sender.mainloop.run, daemon=True)
myThread.start()
myThread2 = threading.Thread(target=receiver.mainloop.run, daemon=True)
myThread2.start()
The targets are GObject.Mainloop() methods.
Afterwards my main program is in an infinite loop.
My problem is that when the execution is terminated by CTRL-C, Keyboardexception is raised for both threads, but the main program does not terminate.
Any ideas how could both the main program and the two threads be terminated by CTRL-C?
ctrl-c issues a SIGINT signal, which you can capture in your main thread for a callback. You can then run whatever shutdown code you want in the callback, maybe a sender/receiver.mainloop.quit() or something.
import threading
import signal
import sys
def loop():
while True:
pass
def exit(signal, frame):
sys.exit(0)
myThread = threading.Thread(target=loop)
myThread.daemon = True
myThread.start()
myThread2 = threading.Thread(target=loop)
myThread2.daemon = True
myThread2.start()
signal.signal(signal.SIGINT, exit)
loop()
I am trying to utilize threading.Thread with Celery to work like a daemon. On a larger scope, the threads will poll hardware sensors as a part of a web UI-powered thermostat, but narrowed-down, this is the bit I'm stuck on:
from celery import Celery
from celery.signals import worker_init
from celery.signals import worker_process_shutdown
from threading import Thread
from threading import Event
from time import sleep
class ThisClass(object):
def __init__(self):
self.shutdown = Event()
self.thread = Thread(target=self.BackgroundMethod)
def Start(self):
self.thread.start()
def Stop(self):
self.shutdown.set()
def BackgroundMethod(self):
while not self.shutdown.is_set():
print("Hello, world!")
sleep(1)
this_class = ThisClass()
celery_app = Celery("tasks", broker="amqp://guest#localhost//")
#worker_init.connect
def WorkerReady(**kwargs):
this_class.Start()
#worker_process_shutdown.connect
def StopPollingSensors(**kwargs):
this_class.Stop()
This Celery script is supposed to create an instance of ThisClass as this_class, and run this_class.Start() when Celery starts. When Celery is shutting down, it is supposed to call this_class.Stop(), which gracefully exits the Thread in ThisClass and Celery cleanly exits.
However, when I hit Ctrl-C in Celery to signal a SIGINT, this_class's thread continues to run and Celery does not exit, even after multiple SIGTERMs are issued. What confuses me is if I slip a print statement in ThisClass.Stop, I see it. Furthermore, if I add sleep(5); this_class.Stop() after this_class.Start(), the thread starts and stops as expected, and Celery will exit normally when issued a SIGINT.
How am I supposed to terminate threading.Thread instances in a Celery-based script?
Consider creating the Event object externally, and passing it to a Thread subclass. The thread loops on the event object. When an external function calls Event.set(), the thread loop exits out of the while loop cleanly.
import sys, time
from threading import Event, Thread, Timer
class ThisClass2(Thread):
def __init__(self, event):
super(ThisClass2,self).__init__()
self.event = event
def run(self):
print 'thread start'
while not self.event.wait(timeout=1.0):
print("thread: Hello, world!")
print 'thread done'
event2 = Event()
x = ThisClass2(event2)
x.start()
print 'okay'
time.sleep(1)
print 'signaling event'
event2.set()
print 'waiting'
x.join()
Example output:
thread start
okay
thread: Hello, world!
signaling event
waiting
thread done
I am writing a python script that needs to run a thread which listens to a network socket.
I'm having trouble with killing it using Ctrl+c using the code below:
#!/usr/bin/python
import signal, sys, threading
THREADS = []
def handler(signal, frame):
global THREADS
print "Ctrl-C.... Exiting"
for t in THREADS:
t.alive = False
sys.exit(0)
class thread(threading.Thread):
def __init__(self):
self.alive = True
threading.Thread.__init__(self)
def run(self):
while self.alive:
# do something
pass
def main():
global THREADS
t = thread()
t.start()
THREADS.append(t)
if __name__ == '__main__':
signal.signal(signal.SIGINT, handler)
main()
Appreciate any advise on how to catch Ctrl+c and terminate the script.
The issue is that after the execution falls off the main thread (after main() returned), the threading module will pause, waiting for the other threads to finish, using locks; and locks cannot be interrupted with signals. This is the case in Python 2.x at least.
One easy fix is to avoid falling off the main thread, by adding an infinite loop that calls some function that sleeps until some action is available, like select.select(). If you don't need the main thread to do anything at all, use signal.pause(). Example:
if __name__ == '__main__':
signal.signal(signal.SIGINT, handler)
main()
while True: # added
signal.pause() # added
It's because signals can only be caught by main thread. And here main thread ended his life long time ago (application is waiting for your thread to finish). Try adding
while True:
sleep(1)
to the end of your main() (and of course from time import sleep at the very top).
or as Kevin said:
for t in THREADS:
t.join(1) # join with timeout. Without timeout signal cannot be caught.
I'm trying to create a kind of non-blocking class in python, but I'm not sure how.
I'd like a class to be a thread itself, detached from the main thread so other threads can interact with it.
In a little example:
#!/usr/bin/python2.4
import threading
import time
class Sample(threading.Thread):
def __init__(self):
super(Sample, self).__init__()
self.status = 1
self.stop = False
def run(self):
while not(self.stop):
pass
def getStatus(self):
return self.status
def setStatus(self, status):
self.status = status
def test(self):
while self.status != 0:
time.sleep(2)
#main
sample = Sample()
sample.start()
sample.test()
sample.setStatus(0)
sample.stop()
What I'd like is having the "sample" instance running as a separate thread (detached from the main one) so, in the example, when the main thread reaches sample.test(), sample (and only "sample") would go to sleep for 2 seconds. In the meanwhile, the main thread would continue its execution and set sample's status to 0. When after the 2 seconds "sample" wakes up it would see the status=0 and exit the while loop.
The problem is that if I do this, the line sample.setStatus(0) is never reached (creating an infinite loop). I have named the threads, and it turns out that by doing this, test() is run by the main thread.
I guess I don't get the threading in python that well...
Thank you in advance
The object's run() method is what executes in a separate thread. When you call sample.test(), that executes in the main thread, so you get your infinite loop.
Perhaps something like this?
import threading
import time
class Sample(threading.Thread):
def __init__(self):
super(Sample, self).__init__()
self.stop = False
def run(self):
while not(self.stop):
print('hi')
time.sleep(.1)
def test(self):
print('testing...')
time.sleep(2)
#main
sample = Sample()
sample.start() # Initiates second thread which calls sample.run()
sample.test() # Main thread calls sample.test
sample.stop=True # Main thread sets sample.stop
sample.join() # Main thread waits for second thread to finish