I've been looking all over google and can't seem to get this working.
I'm trying to thread 2 functions, both of which are infinite loops.
Looking at the extract below, it only starts the 1st thread and does not proceed to the next one in line.
PS: When I swap the 2 threads around, then I have the same problem with the 2nd thread.
def syslog_service():
syslog_server = socketserver.UDPServer((syslog_host,syslog_port), Syslog_Server)
syslog_server.serve_forever()
def cleanup_old_logs_service():
# lock = threading.Lock()
# threading.Thread.__init__(self)
global syslog_retention_hours
global RUNNING
while RUNNING:
# cleanup_old_logs_service.lock.acquire()
cleanup.old_logs(syslog_retention_hours)
# cleanup_old_logs_service.lock.release()
time.sleep(10)
if __name__ == "__main__":
try:
logger.info("Starting main thread")
config()
logger.info("Starting system testing")
test()
logger.info("Config loaded")
thread1 = cleanup_old_logs_service()
thread2 = syslog_service()
thread1.start()
logger.info("Syslog cleanup service running")
thread2.start()
logger.info("Syslog server running")
The reason why only the first thread is executed is that you actually have ONLY one thread in your program. When you write thread1 = cleanup_old_logs_service() and thread2 = syslog_service()you are not creating new threads, but just assigning the return values of your functions to 2 different variables. For this reason, as soon as the program encounters thread1, it executes cleanup_old_logs_service() and gets stuck in an infinite loop.
To create a new thread, I would import the threading module, create a new threadObj object and start the thread as follows:
import threading
threadObj = threading.Thread(target=cleanup_old_logs_service)
threadObj.start()
This way, the function cleanup_old_logs_service() will be executed in a new thread.
By saying thread1 = cleanup_old_logs_service() you are actually executing the function cleanup_old_logs_service not saving a reference to a thread. You would have to say
import threading # If you have not already
thread1 = threading.Thread(target=cleanup_old_logs_service)
thread2 = threading.Thread(target=syslog_service)
# Now you can start the thread
thread1.start()
logger.info("Syslog cleanup service running")
thread2.start()
logger.info("Syslog server running")
You can look at https://docs.python.org/3.5/library/threading.html for documentation and https://pymotw.com/2/threading/ for examples, because I believe you would need to use locks to manage access to your resources
Related
i wrote a code in python with 2 infinite loop like this:
import threading
import time
ticker = 0
def ticking():
global ticker
while True:
time.sleep(1)
ticker +=1
print("ticker = {}".format(ticker))
def main_line():
while True:
print("Hello world")
time.sleep(4)
t1 = threading.Thread(target = ticking)
t2 = threading.Thread(target = main_line)
t1.start()
t2.start()
#t1.join()
if __name__ == "__main__":
t1.join()
#t2.join()
If i don't join any thread it's not working, but when i join 1 thread, another thread is work too but i don't know why?
Can anyone explain for me?
Join is used to block the calling method until the thread finishes, throws an exception or time out.
join([timeout]) Wait until the thread terminates. This blocks the
calling thread until the thread whose join() method is called
terminates – either normally or through an unhandled exception – or
until the optional timeout occurs.
In your case, you have started both threads. So both threads are working. But once you block the main thread by t1.join(), both running threads will be visible.
it is because you also "start" another thread. If you make a comment on t2.start(), then the thread is only working on t1.
t1.start()
# t2.start()
I have a very simple class with one attribute and one method. i would like the method to run based on the value of the attribute. below is the class code:
class TestWhile()
def __init__(self):
self.status = "OFF"
def StreamV(self):
while self.Status == "ON"
print "nonstop"
basically what I want to do is set Status to ON, then run StreamV until Status is set to off. This is what i want as follows:
P = TestWhile()
T.Status = "ON"
T.StreamV()
T.Status = "OFF"
When I run the above test, it never makes it to the Status = "OFF" line and infinitely runs the loop. How can I fix this?
your call to T.StreamV() does what is commonly referred to as Busy looping and blocks the main thread. What you have effectively described you want is a background thread to update some value until a signal comes in (from your T.Status attribute)
Threading is relatively approachable for simple problems, and is an incredibly useful tool to get to know. From a super wide viewpoint a thread in python is a function that can run at the same time the main script is doing something else. In this regard python threads are indeed created by passing them a function to execute.
Example:
import threading
import time
class TestWhile(object):
def __init__(self):
self.status = "OFF"
self.streamVthread = threading.Thread(target=self.StreamV) #create a thread for our streamV function
def StreamV(self):
print "starting thread"
while self.Status == "ON":
print "nonstop"
time.sleep(1)
print "stopping thread"
T = TestWhile() #our thread is actually created here, but is hasn't started yet
print 'T.Status -> "ON"'
T.Status = "ON" #T.StreamV could be modified to run at creation and wait for this to change to "ON"
T.streamVthread.start() #this calls the T.StreamV function in a separate thread
time.sleep(6)
T.Status = "OFF"
print 'T.Status -> "OFF"'
I've added a bunch of print statements to help you understand the flow of the program. Please comment with any questions.
Edit: passing arguments to a thread
Threads exist in the same namespace as the main thread, so if they share a variable with the main script they will both have access to it. This can cause problems with multiple threads accessing the same thing at the same time (read more on locks and other mutex constructs). Passing arguments at creation of the thread however can be done as such:
import threading
import time
def sayHello(after_secs, name):
time.sleep(after_secs)
print("hello from {}".format(name))
thread1 = threading.Thread(target=sayHello, args=(3,"thread1"))
thread2 = threading.Thread(target=sayHello, args=(1,"thread2"))
thread3 = threading.Thread(target=sayHello, args=(5,"thread3"))
print "starting thread1"
thread1.start()
print "starting thread2"
thread2.start()
print "starting thread3"
thread3.start()
thread1.join() #wait for thread1 to finish
print "thread1 is done"
thread2.join() #wait for thread2 to finish
print "thread2 is done"
thread3.join() #wait for thread3 to finish
print "thread3 is done"
See if you can determine why these print statements happen in the order they do..
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 have following code which compares user input
import thread,sys
if(username.get_text() == 'xyz' and password.get_text()== '123' ):
thread.start_new_thread(run,())
def run():
print "running client"
start = datetime.now().second
while True:
try:
host ='localhost'
port = 5010
time = abs(datetime.now().second-start)
time = str(time)
print time
client = socket.socket()
client.connect((host,port))
client.send(time)
except socket.error:
pass
If I just call the function run() it works but when I try to create a thread to run this function, for some reason the thread is not created and run() function is not executed I am unable to find any error..
Thanks in advance...
you really should use the threading module instead of thread.
what else are you doing? if you create a thread like this, then the interpreter will exit no matter if the thread is still running or not
for example:
import thread
import time
def run():
time.sleep(2)
print('ok')
thread.start_new_thread(run, ())
--> this produces:
Unhandled exception in thread started by
sys.excepthook is missing
lost sys.stderr
where as:
import threading
import time
def run():
time.sleep(2)
print('ok')
t=threading.Thread(target=run)
t.daemon = True # set thread to daemon ('ok' won't be printed in this case)
t.start()
works as expected. if you don't want to keep the interpreter waiting for the thread, just set daemon=True* on the generated Thread.
*edit: added that in example
thread is a low level library, you should use threading.
from threading import Thread
t = Thread(target=run, args=())
t.start()
I'm sorry if it is a stupid question. I am trying to use a number of classes of multi-threading to finish different jobs, which involves invoking these multi-threadings at different times for many times. But I am not sure which method to use. The code looks like this:
class workers1(Thread):
def __init__(self):
Thread.__init__(self)
def run(self):
do some stuff
class workers2(Thread):
def __init__(self):
Thread.__init__(self)
def run(self):
do some stuff
class workers3(Thread):
def __init__(self):
Thread.__init__(self)
def run(self):
do some stuff
WorkerList1=[workers1(i) for i in range(X)]
WorkerList2=[workers2(i) for i in range(XX)]
WorkerList2=[workers3(i) for i in range(XXX)]
while True:
for thread in WorkerList1:
thread.run (start? join? or?)
for thread in WorkerList2:
thread.run (start? join? or?)
for thread in WorkerList3:
thread.run (start? join? or?)
do sth .
I am trying to have all the threads in all the WorkerList to start functioning at the same time, or at least start around the same time. After sometime once they were all terminated, I would like to invoke all the threads again.
If there were no loop, I can just use .start; but since I can only start a thread once, start apparently does not fit here. If I use run, it seems that all the threads start sequentially, not only the threads in the same list, but also threads from different lists.
Can anyone please help?
there are a lot of misconceptions here:
you can only start a specific instance of a thread once. but in your case, the for loop is looping over different instances of a thread, each instance being assigned to the variable thread in the loop, so there is no problem at all in calling the start() method over each thread. (you can think of it as if the variable thread is an alias of the Thread() object instantiated in your list)
run() is not the same as join(): calling run() performs as if you were programming sequentially. the run() method does not start a new thread, it simply execute the statements in in the method, as for any other function call.
join() does not start executing anything: it only waits for a thread to finish. in order for join() to work properly for a thread, you have to call start() on this thread first.
additionally, you should note that you cannot restart a thread once it has finished execution: you have to recreate the thread object for it to be started again. one workaround to get this working is to call Thread.__init__() at the end of the run() method. however, i would not recommend doing this since this will disallow the use of the join() method to detect the end of execution of the thread.
If you would call thread.start() in the loops, you would actually start every thread only once, because all the entries in your list are distinct thread objects (it does not matter they belong to the same class). You should never call the run() method of a thread directly -- it is meant to be called by the start() method. Calling it directly would not call it in a separate thread.
The code below creates a class that is just a thread but the start and calls the initialization of the Thread class again so that the thread doesn't know it has been called.
from threading import Thread
class MTThread(Thread):
def __init__(self, name = "", target = None):
self.mt_name = name
self.mt_target = target
Thread.__init__(self, name = name, target = target)
def start(self):
super().start()
Thread.__init__(self, name = self.mt_name, target = self.mt_target)
def run(self):
super().run()
Thread.__init__(self, name = self.mt_name, target = self.mt_target)
def code():
#Some code
thread = MTThread(name = "SomeThread", target = code)
thread.start()
thread.start()
I had this same dilemma and came up with this solution which has worked perfectly for me. It also allows a thread-killing decorator to be used efficiently.
The key feature is the use of a thread refresher which is instantiated and .started in main. This thread-refreshing thread will run a function that instantiates and starts all other (real, task-performing) threads. Decorating the thread-refreshing function with a thread-killer allows you to kill all threads when a certain condition is met, such as main terminating.
#ThreadKiller(arg) #qu'est-ce que c'est
def RefreshThreads():
threadTask1 = threading.Thread(name = "Task1", target = Task1, args = (anyArguments))
threadTask2 = threading.Thread(name = "Task2", target = Task2, args = (anyArguments))
threadTask1.start()
threadTask2.start()
#Main
while True:
#do stuff
threadRefreshThreads = threading.Thread(name = "RefreshThreads", target = RefreshThreads, args = ())
threadRefreshThreads.start()
from threading import Thread
from time import sleep
def runA():
while a==1:
print('A\n')
sleep(0.5)
if __name__ == "__main__":
a=1
t1 = Thread(target = runA)
t1.setDaemon(True)
t1.start()
sleep(2)
a=0
print(" now def runA stops")
sleep(3)
print("and now def runA continue")
a=1
t1 = Thread(target = runA)
t1.start()
sleep(2)