How to continue with the main program when threading - python

I'm trying to run a thread in python and am fairly new at it. While going through the basics, when I start a thread, the program doesn't continue with the main program and is stuck in the thread. i.e. it prints only "hello world" and never prints "hi there".
from threading import Thread
import time
def hello_world():
while True:
print("hello world")
time.sleep(5)
t = Thread(target = hello_world())
t.start()
print("hi there")
I'm using spyder IDE.
I searched online for some basic programs in threading but for those, the code works.
How should I proceed?

Your problem is in the line t = Thread(target = hello_world()).
You are trying to create a Thread with the target argument. According to the order of evaluation, Python first needs to know what to assign to target, so it evaluates the RHS. In your case the RHS is hello_world(). So the function is already being called in that exact moment!
So the function executes and enters the infinite loop and the Thread is never even created and your program is stuck.
What you would want to do is pass to target a mere reference to the function, so change said line to:
t = Thread(target = hello_world)
And now the RHS is evaluated as a reference to the given function, and behind the scenes the Thread will be created, making the call to that function, and your main Thread will keep running as expected.

Related

Python: How to wait until a function has been called in a different thread?

I have a function in thread A which needs to wait until a function in thread B is called.
The function in thread B is called periodically, so it just needs to wait until the next time it is called. This allows me to sync up with it.
How would I do this?
(Sorry if this is trivial.)
It may be a principle of computer science that no multithreading question is trivial.
There are various ways to do this, but one of the simplest involves the use of a threading.Event object. Events are the simplest of the so-called synchronization primitives. See the manual section on the threading module for more ideas. Here is a working example:
#! python3.8
import threading
import time
t0 = time.time()
def elapsed_time():
return time.time() - t0
class StopMe:
def __init__(self):
self.running = True
def main():
ev1 = threading.Event()
stop = StopMe()
th1 = threading.Thread(target=thread1, args=(ev1, stop))
th1.start()
for _ in range(10):
ev1.wait()
print("The function was just called", elapsed_time())
ev1.clear()
stop.running = False
th1.join()
print("Exit", elapsed_time())
def thread1(event, stop):
def a_function():
event.set()
print("I am the function", elapsed_time())
while stop.running:
time.sleep(1.0)
a_function()
main()
Output:
I am the function 1.0116908550262451
The function was just called 1.0116908550262451
I am the function 2.0219264030456543
The function was just called 2.0219264030456543
I am the function 3.0322916507720947
The function was just called 3.0322916507720947
I am the function 4.033170938491821
The function was just called 4.033170938491821
I am the function 5.043376445770264
The function was just called 5.043376445770264
I am the function 6.043909788131714
The function was just called 6.043909788131714
I am the function 7.054021596908569
The function was just called 7.054021596908569
I am the function 8.06399941444397
The function was just called 8.06399941444397
I am the function 9.064924716949463
The function was just called 9.064924716949463
I am the function 10.066757678985596
The function was just called 10.066757678985596
I am the function 11.076870918273926
Exit 11.076870918273926
Some things to note here:
Once you put a synchronization primitive into your code, you need to give some thought about how to terminate the thread gracefully, and how to terminate the application as a whole. In this example, the threads communicate through the little "StopMe" object, and through the Event object. Note that the main thread may have to wait one second until the secondary thread finishes its sleep function. That occurs if thread1 begins its time delay before the main thread calls the join function. That didn't happen in my test run but it might, depending on how CPU time slices are given to the different threads. If that's not acceptable to you, you have to write more code to get around it.
Also note that the function call ev1.wait() will block the main thread until the event is set from the secondary thread. In a GUI application that is not what you want.
I ran this with Python3.8 but the program doesn't use any version-specific features, so it should work the same with any reasonably recent version of Python.

How to call a simple function and simultaneously run the following line(s)?

I know there is something called thread, but I am confused by those complex information all over Google. myFunc() takes a little time (not computationally expensive, say play a short mp3 file).
What I want to do is call myFunc() and don't need to wait for it to return to run the following lines of code. Furthermore, I don't need to keep anything related to myFunc(arg), I only need it to be executed only.
while(True):
......
myFunc(arg)
###some
###lines
###of
###code
Sorry for my bad English. Cheers!
from threading import Thread
def myFunc(arg):
# run code here
while(True):
thread = Thread(target = myFunc, args = (arg, ))
thread.start() # starts the thread, executes the function
###some
###lines
###of
###code
thread.join() # wait for myFunc to finish
You can do similarly with processes instead of threads.
Might want take a look into pools if you want to perform a list of arguments with the same function. You can call imap and iterate the results and call the rest of the code.

Python: I start a new thread, and my program pauses until the thread is finished

When I try to start a new thread, my entire program stops until the thread's function finishes. I am trying to make the thread start and continue while my program runs at the same time.
Code:
def do_python(string):
while True:
exec(string, globals())
time.sleep(0.1)
getKeyThread = threading.Thread(target=do_python("key = cpc.get_key()"), daemon=True).start()
time.sleep(0.2)
while True:
if key == 9:
print("Tab pressed.")
exit()
I have imported all of the required modules, so that is not the problem. Any functions used in here that aren't defined have been defined elsewhere and work perfectly fine. I haven't included my entire program here, because it is far too big to paste here.
By doing
do_python("key = cpc.get_key()")
you are actually calling, in your main thread, the do_python function (which has an infinite loop and will never stop running). Since the function never returns anything, it will just keep running forever. If it did return something, you'd probably get an error unless whatever is returned in a callable object.
The argument target requires a callable, so you have to pass your function to it
getKeyThread = threading.Thread(target=do_python, args=some_args, daemon=True).start()

How to run and stop an infinite loop in a python thread

I need to run a (series of) infinite loops that must be able to check an externally set condition to terminate. I thought the threading module would allow that, but my efforts so fare have failed. Here is an example of what I am trying to do:
import threading
class Looping(object):
def __init__(self):
self.isRunning = True
def runForever(self):
while self.isRunning == True:
"do stuff here"
l = Looping()
t = threading.Thread(target = l.runForever())
t.start()
l.isRunning = False
I would have expected t.start to run in a separate thread, with l's attributes still accessible. This is not what happens. I tried the snippet above in the python shell (IPython). Execution of t start immediately after instantiation and it blocks any further input.
There is obviously something I am not getting right about the threading module.
Any suggestion on how to solve the problem?
You are calling runForever too early. Use target = l.runForever without parentheses.
A function call is not evaluated until after its arguments are. When you write runforever(), it calls the function right then, before even creating the thread. By just passing runForever, you pass the function object itself, which the threading apparatus can then call when it is ready. The point is that you don't actually want to call runForever; you just want to tell the threading code that runForever is what it should call later.

Python thread holds up the rest of the script

Running Python 3.2 on Windows 7 Pro 64 Bit.
OK I have some very basic code here that's just not behaving like I want it to.
#!/usr/bin/env python
import time
import threading
def shutdown(sleeptime):
time.sleep(sleeptime)
print('I have executed')
threading.Thread(target = shutdown(5)).start()
print('I go first')
The idea being that the script runs, it starts a thread which sleeps for 5 seconds then prints out 'I have executed'. In the meantime the script keeps going and prints out 'I go first'.
What actually happens is that the script starts the thread, everything waits for it to finish and then it continues. Clearly I'm not doing the threading correctly but I'm having trouble finding simple examples of threading with Python 3.
Your statement:
threading.Thread(target = shutdown(5)).start()
can be equivalently written as:
x = shutdown(5)
threading.Thread(target = x).start()
I.e. you are calling shutdown first, then passing the result to the Thread constructor.
You need to pass your function, without calling it, and your argument list, to Thread separately:
threading.Thread(target = shutdown, args = (5,)).start()
Your target is not evaluating to a function, but rather the value of shutdown(5), which is None. You probably want it to be more like:
def shutdown(sleeptime):
def shutter_downer():
time.sleep(sleeptime)
print('I have executed')
return shutter_downer

Categories

Resources