Why is my main thread not completing its task? - python

In the below code the daemon thread is only giving the output whereas the main thread is not. If the main thread works independently of the "x"(daemon) thread then why isn't it asking for input(it is just giving the output of the daemon thread).
import threading
import time
def daemon_thread():
print()
timer = 0
while True:
time.sleep(1)
timer += 1
print(timer, "s")
x = threading.Thread(target=daemon_thread(), args=())
x.start()
answer = input("Do you wish to exit?")
print(threading.active_count())

For the Thread constructor you should pass a reference to the appropriate function. You do not call the function. Therefore:
x = threading.Thread(target=daemon_thread)

You have call your function inside thread class that's why main thread is not working
X = threading.Thread(target=daemon_thread())
# Wrong
X = threading.Thread(target=daemon_thread)
# Right

Related

Run multiple python scripts in parallel from master script

I'd like to run multiple python scripts in parallel and start them from a master script. I did find solutions for this in previously asked questions, however, none of these worked if the scripts running in parallel contained loops.
Let's for example define two scripts.
Script 1:
array_1 = []
x = 0
while True:
array_1.append(x)
x = x + 1
Script 2:
array_2 = []
x = 0
while True:
array_2.append(x)
x = x + 1
Now I want to run both processes simultaneously. Previous solutions suggested the following code for a master script:
import script_1, script_2
exec(open(script_1))
exec(open(script_2))
While this is a solution for starting scripts from within another script, however, this will not run the two scripts in parallel.
What should such a master script actually look like ?
Thanks for your suggestions!
Edit
I tried the following threading approach:
def function_1():
print('function 1 started...')
while True:
print('1')
sleep(1)
def function_2():
print('function 2 started...')
while True:
print('2')
sleep(1)
thread_1 = Thread(target=function_1())
thread_2 = Thread(target=function_2())
thread_1.start()
thread_2.start()
thread_1.join()
thread_2.join()
print("thread finished")
It doesn't work, only the first function gets started so I get the following output:
function 1 started...
1
1
1
1
1
1
When you want to spawn a new thread, you need to pass the address of the function you want the thread to execute, and not to call it. What you are doing here is essentially spawning a new thread that immediately calls function_1() which of course runs forever.
Also, you won't be able to reach this line of code:
print("thread finished")
As the threads are executing a while loop - forever, so it is redundent..
from time import sleep
from threading import Thread
def function_1():
print('function 1 started...')
while True:
print('1')
sleep(1)
def function_2():
print('function 2 started...')
while True:
print('2')
sleep(1)
thread_1 = Thread(target=function_1)
thread_2 = Thread(target=function_2)
thread_1.start()
thread_2.start()
thread_1.join()
thread_2.join()
# print("thread finished") - redundant

How do I thread these functions?

I am trying to code an alarm in python that has 6 functions that need to multithread. 5 of these are alarms and one of them displays the time. The threads need to start and stop whenever the menu option is selected and when the alarm rings. The Display thread is the only thread that keeps going until the program stops. My current code for the alarm looks like this (I've removed a lot for the sake of clarity)
class TAlarm1 (threading.Thread):
def Alarm1():
while True:
#code which keeps running until the time is equal to the input given (expected to thread)
thread1 = threading.Thread(target=TAlarm1)
thread1.start()
def AlarmSelector():
print("Select an Alarm") #5 alarms will be added however each one accomplishes the same task. all of them need to run simultaneously
choice = int(input())
if choice == 1:
ala = TAlarm1()
ala.Alarm1()
if choice == 6:
DisplayTime() #goes back to displaying time
Whenever I run this code, the program displays no errors however it does not run the code in TAlarm1().
How can I solve this problem?
While your intent isn't clear to me. Here is how you can subclass Thread with its run method overridden and start it conditionally.
import threading
class TAlarm1 (threading.Thread):
def run(self):
n =4
while True:
#code which keeps running until the time is equal to the input given (expected to thread)
print(n,end=' | ')
n -= 1
if n < 0:
break
print()
t1 = TAlarm1()
if True:
t1.start()
A thread can only be started once so you have to make a new one every time you need it to run.
>>> t = TAlarm1()
>>> t.start()
4 | 3 | 2 | 1 | 0 |
>>> t.start()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python38\lib\threading.py", line 848, in start
raise RuntimeError("threads can only be started once")
RuntimeError: threads can only be started once
>>> t = TAlarm1()
>>> t.start()
4 | 3 | 2 | 1 | 0 |
>>>
The target parameter of Thread takes a callable. A class is a callable, but calling it just creates an instance of the class. Pass it a function instead:
import threading
def Alarm1():
print('Alarm1 called')
thread1 = threading.Thread(target=Alarm1)
thread1.start()
There are two basic ways of implementing threaded code in Python. You seem to have half of each.
The first implementation model is to put the logic to run in the thread into a function, then pass that function as the target argument when you create a threading.Thread instance:
import threading
import time
def worker(n):
for i in range(n):
print(i)
time.sleep(0.5)
my_thread = threading.Thread(target=worker, args=(10,))
my_thread.start()
# do other stuff in the main thread, if desired
my_thread.join()
The other implementation approach is to subclass threading.Thread and put the code to be run in the thread inside of the run method (or in other methods called from run). This is especially useful if your thread code has some complicated state and you want to be able to use additional methods to manipulate that state while the thread is running:
class MyThread(threading.Thread):
def __init__(self, n):
super().__init__()
self.n = n
self.unpaused = threading.Event()
self.unpaused.set() # we start unpaused
def run(self):
for i in range(self.n):
self.unpaused.wait() # block if we're paused
print(i)
time.sleep(0.5)
def pause(self):
self.unpaused.clear()
def unpause(self):
self.unpaused.set()
my_thread = MyThread(10)
my_thread.start()
# an example of inter-thread communication, we pause and unpause our thread using its methods
time.sleep(2)
my_thread.pause()
time.sleep(2)
my_thread.unpause()
my_thread.join()

twisted - run in a thread

new to python
new to twisted
My team wants me to make some existing code run in a seperate thread.
I've come up with a fictional example:
from twisted.internet import threads, reactor
from twisted.internet.defer import inlineCallbacks
from time import sleep
class SomeClass(object):
def __init__(self):
self.working = False
def set_working(self, is_working):
self.working = is_working
print 'Flag set to {}'.format(is_working)
#inlineCallbacks
def do_worker_thread(self):
# I want to make this call on the main thread
self.set_working(True)
# I want to do all this garbage on a separate thread and keep trucking on the main thread
# This mimics some calls in the real code. There is a call to deferToThread and a try
# except block there.
def thread_proc():
try:
for i in range(0, 100):
print 'Step %d starting'.format(i)
self.execute_step(i)
except Exception:
print 'An exception happened'
reactor.callInThread(thread_proc)
# When the worker thread is done, I want to call back 'on_thread_work_done'
def execute_step(self, num):
sleep(num)
print 'Worker thread: %d'.format(num)
def on_thread_work_done(self):
"""I want to be called back when the worker thread is done"""
self.set_working(False)
#inlineCallbacks
def do_main_thread(self):
for c in range(ord('a'), ord('z')+1):
sleep(c)
print 'Main thread: {}'.format(c)
if __name__ == "__main__":
someClass = SomeClass()
result = someClass.do_worker_thread()
result.addCallback(someClass.do_main_thread())
reactor.run()
The stuff on do_worker_thread currently runs on the main thread. I put a comment in there were I want it to run in a seperate thread. It is important that do_worker_thread returns immediately.
I expect the output to look something like:
Flag set to True
Step 0 starting
Main thread: a
Worker thread: 0
Worker thread: 1
Main thread: b
Worker thread: 2
Main thread: c
...
How can I alter what's in do_worker_thread, such that my set_working calls are on the main thread and it isn't set to False until the worker thread is done its work?
Try giving this a shot. It uses callFromThread() to schedule the work on the main thread.
from twisted.internet import threads, reactor
from twisted.internet.defer import inlineCallbacks, returnValue
from time import sleep
class SomeClass(object):
def __init__(self):
self.working = False
def set_working(self, is_working):
self.working = is_working
print 'Flag set to {}'.format(is_working)
#inlineCallbacks
def do_worker_thread(self):
# I want to make this call on the main thread
self.set_working(True)
# I want to do all this garbage on a separate thread and keep trucking on the main thread
# This mimics some calls in the real code. There is a call to deferToThread and a try
# except block there.
def thread_proc():
try:
for i in xrange(0, 10):
print 'Step {} starting'.format(i)
self.execute_step(i)
except Exception:
print 'An exception happened'
yield threads.deferToThread(thread_proc)
# When the worker thread is done, I want to call back 'on_thread_work_done'
self.on_thread_work_done()
returnValue(17)
def execute_step(self, num):
sleep(1)
print 'Worker thread: {}'.format(num)
def on_thread_work_done(self):
"""I want to be called back when the worker thread is done"""
self.set_working(False)
def do_main_thread(self):
for i in [chr(x) for x in range(ord('a'), ord('z')+1)]:
print 'Main thread: {}'.format(i)
sleep(1)
def thread_done(self, result):
print 'Thread done: {}'.format(result)
if __name__ == "__main__":
someClass = SomeClass()
# Schedule the threaded work
result = someClass.do_worker_thread().addCallback(someClass.thread_done)
# Schedule the main thread work
reactor.callFromThread(someClass.do_main_thread)
reactor.run()
You can use either callFromThread or blockingCallFromThread.

Update Tkinter widget from main thread after worker thread completes

I need to update the GUI after a thread completes and call this update_ui function from main thread (like a software interrupt maybe?). How can a worker thread call a function in the main thread?
Sample code:
def thread():
...some long task
update_ui() #But call this in main thread somehow
def main():
start_new_thread(thread)
...other functionality
def update_ui():
Tkinter_widget.update()
I tried to use Queue or any flag accessible to both threads but I have to wait/poll continuously to check if the value has been updated and then call the function - this wait makes the UI unresponsive. e.g.
flag = True
def thread():
...some long task
flag = False
def main():
start_new_thread(thread)
while(flag): sleep(1)
update_ui()
...other functionality
Your code appears to be somewhat hypothetical. Here is some that accomplishes that does what you describe. It creates three labels and initializes their text. It then starts three threads. Each thread updates the tkinter variable associated with the label created in the main thread after a period of time. Now if the main thread really needs to do the updating, queuing does work, but the program must be modified to accomplish that.
import threading
import time
from tkinter import *
import queue
import sys
def createGUI(master, widget_var):
for i in range(3):
Label(master, textvariable=widget_var[i]).grid(row=i, column=0)
widget_var[i].set("Thread " + str(i) + " started")
def sometask(thread_id, delay, queue):
print("Delaying", delay)
time.sleep(delay)
tdict = {'id': thread_id, 'message': 'success'}
# You can put simple strings/ints, whatever in the queue instead
queue.put(tdict)
return
def updateGUI(master, q, widget_var, td):
if not q.empty():
tdict = q.get()
widget_var[tdict['id']].set("Thread " + str(tdict['id']) + " completed with status: " + tdict['message'])
td.append(1)
if len(td) == 3:
print("All threads completed")
master.after(1000, timedExit)
else:
master.after(100, lambda w=master,que=q,v=widget_var, tcount=td: updateGUI(w,que,v,td))
def timedExit():
sys.exit()
root = Tk()
message_q = queue.Queue()
widget_var = []
threads_done = []
for i in range(3):
v = StringVar()
widget_var.append(v)
t = threading.Thread(target=sometask, args=(i, 3 + i * 3, message_q))
t.start()
createGUI(root, widget_var)
updateGUI(root,message_q, widget_var, threads_done)
root.mainloop()

Thread error can't start new thread

I am trying to run as many thread as possible. however I have problem here
C:\Python27\lib\threading.py
_start_new_thread(self.__bootstrap, ())
thread.error: can't start new thread
When I call this
class startSleep(threading.Thread):
import threading
import time
class startSleep(threading.Thread):
def run(self):
current = x
# input of the treads
thread = input("Threads: ")
nload = 1
x = 0
# Threads
for x in xrange(thread):
startSleep().start()
time.sleep(0.003)
print bcolors.BLUE + "Thread " + str(x) + " started!"
I want to run as many thread as possible
There is a limit to how many threads you can start that the system can simultaneously handle, you need to either close these threads from within (by having the function you thread either finish or while loops break) or try joining the threads by creating a list of these threads and joining the list items.
list_of_threads.append(example)
example.start()
for thread in list_of_threads:
thread.join()
Now assuming you want to add unlimited threads, you need functions to simply finish, this code never ends with threads -> your unlimited threads:
from threading import Thread
def sleeper(i):
print(i)
i = 0
while(1):
t = Thread(target=sleeper, args=(i,))
t.start()
i += 1

Categories