I am new with python and I am trying to made code that stop work in case timeout has been reached. But it seems that the tread correctly timeout but it does not stop the work.
Here is my code:
import threading
import time
import sys
def main():
t1_stop= threading.Event()
t1 = threading.Thread(target=thread1, args=(5, t1_stop))
t1.setDaemon(False)
t1.start()
print 'thread 1 set'
while True:
print "blablabla"
time.sleep(1)
def thread1(time, stop_event):
while(not stop_event.is_set()):
#equivalent to time.sleep()
print 'thread 1'
stop_event.wait(time)
main()
UPD
I update code using Timer instead of time.time.
def main():
stopped = threading.Event()
timeout = 10
#thread = threading.Thread(target=my_thread, args=(timeout, stopped))
timer = Timer(timeout, my_thread(timeout,stopped))
thread = threading.Thread((timer).start())
thread.setDaemon(False)
#thread.start()
print 'thread 1 set'
start_t = time.time()
while thread.is_alive():
print "doing my job"
if not stopped.is_set():# and (time.time() - start_t) > timeout:
stopped.set()
#time.sleep(1)
def my_thread(time, stopped):
while not stopped.wait(time):
print('thread stopped')
main()
But I still get original problem the script does not stopped and continue.
Thanks in advance for your help.
you must call t1_stop.set() in main function for stop thread.
something like:
import threading
import time
import sys
def main():
stopped = threading.Event()
thread = threading.Thread(target=my_thread, args=(5, stopped))
thread.setDaemon(False)
thread.start()
print 'thread 1 set'
time.sleep(5) # +
stopped.set() # +
while True:
print "blablabla"
time.sleep(1)
def my_thread(time, stopped):
while not stopped.wait(time):
print('thread 1')
main()
with 'blablabla':
def main():
...
thread.start()
print 'thread 1 set'
start_t = time.time()
while True:
print "blablabla"
if not stopped.is_set() and (time.time() - start_t) > 5:
stopped.set()
time.sleep(1)
UPD:
exiting from while:
while thread.is_alive():
print "blablabla"
if not stopped.is_set() and (time.time() - start_t) > 5:
stopped.set()
time.sleep(1)
Related
I am trying to run two functions in parallel:
Timer
Input field
Program should terminate either when Timer ends or when user provides an answer.
Everything is working fine, but when the time is up I still can input an answer, and I want process to terminate.
Can somebody help me with that issue ?
Thanks !
Here is my code:
import sys
import time
import threading
def countdown2(seconds):
global stop_timer
stop_timer = False
start = time.time()
while not stop_timer:
if time.time() - start >= seconds:
stop_timer = True
print(f'End of time {time.time() - start}')
print(f'End of time in {time.time() - start}')
countdown_thread = threading.Thread(target=countdown2, args=(5,))
countdown_thread.start()
while not stop_timer:
answer = input('Provide answer: ')
if answer:
stop_timer = True
break
print('End')
Here's an example of how you could do this:
from threading import Thread
import time
import signal
import os
got_input = False
def countdown(duration):
global got_input
for _ in range(duration):
time.sleep(1)
if got_input:
return
if not got_input:
os.kill(os.getpid(), signal.SIGINT)
def main():
global got_input
(t := Thread(target=countdown, args=[5])).start()
try:
answer = input('Please enter a value: ')
got_input = True
print(f'You entered: {answer}')
except KeyboardInterrupt:
print('\nToo slow')
finally:
t.join()
if __name__ == '__main__':
main()
I know there's something stupid I'm doing, but I can't figure this out! I'm testing by doing 1 thread. It's supposed to add up to ten items in the queue, wait for it to finish, and then say "Finished". The thread function has q.task_done() at the end of it. But it'll say "Task Done" but then it just pauses and doesn't ever say "Finished".
def helper(q):
print("Started")
....
q.task_done()
print("Task done")
def main():
q = Queue(maxsize=0)
recid = 9000000
num_threads = 1
for i in range(num_threads):
worker = Thread(target=helper, args=(q))
worker.setDaemon(True)
worker.start()
while recid > 0:
batch.clear()
for x in range(10):
q.put(recid)
print("Added request.")
recid -= 1
print("Waiting for threads to finish.")
q.join()
print("Finished")
worker was dead before you called q.join(). maybe try to add some delays in helper() waiting for q.put()
def helper(q):
print("Started")
time.sleep(1) # wait for main() q.put()
while not q.empty(): # until queue is empty
print("request", q.get())
q.task_done() # trigger q.join in main()
print("Task done")
time.sleep(1) # wait for next q.put() if exists
Updated:
Basically, q.task_done() in helper() triggers q.join() in main() and worker.join() will be triggered once helper() is exited. An example code is as followed:
def main():
q = Queue(maxsize=0)
recid = 100
num_threads = 4
while recid > 0:
for i in range(num_threads):
print('''******** Hired Worker %d ********'''%(i),)
worker = Thread(target=helper, args=(q,))
worker.setDaemon(True)
worker.start()
# batch.clear()
for x in range(3):
q.put(recid)
print("Request Worker %d to do %d."%(i, recid))
recid -= 1
##############################################################
# Comment these lines when you are ready to test multiThread
##############################################################
print("Waiting Worker %d to finish %d."%(i, recid))
q.join() # triggered by q.task_done in helper()
print("Worker %d Finished %d"%(i, recid))
print("Waiting for Worker %d to leave."%i)
worker.join() # triggered once helper() is exited
print("!!!!!!!! Worker %d left !!!!!!!!"%i)
##############################################################
time.sleep(5) # wait until all requests are finished.
print("Finished")
Once you are happy with join() of Thread and Queue. You may try multithreading by commenting that block of code.
I have tried to use multi-threading for limiting the input time for the user, but this code doesn't seem to work.
# giving the user less than 5 seconds to enter a number
import time
from threading import Thread
def ask():
start_time = time.time()
a = float(input("Enter a number:\n"))
time.sleep(0.001)
def timing():
if time.time() - start_time > 5:
print("Time's Up")
quit()
time.sleep(0.001)
t1 = Thread(target=ask)
t2 = Thread(target=timing)
t1.start()
t2.start()
t1.join()
t2.join()
You need to put timing function in infinite mode. Bcz it's running only one time.
Try below code:
import time
import os
from threading import Thread
start_time = time.time()
a = None
def ask():
global start_time
start_time = time.time()
global a
a = float(input("Enter a number:\n"))
time.sleep(0.001)
def timing():
while True:
global a
if a is not None:
break
if time.time() - start_time > 5:
print("Time's Up")
os._exit(1)
time.sleep(0.001)
t1 = Thread(target=ask)
t2 = Thread(target=timing)
t1.start()
t2.start()
t1.join()
t2.join()
I don't like global variables but the following piece of code seems to work well for your need:
import time
from threading import Thread
import sys
start_time = 0
timeUp = False
def ask():
global start_time, timeUp
start_time = time.time()
a = float(input("Enter a number:\n"))
time.sleep(0.001)
if a and (not timeUp):
print('This is a: ', a)
def timing():
global timeUp
while True:
if time.time() - start_time > 5:
print("Time's Up")
timeUp = True
sys.exit()
time.sleep(0.001)
t1 = Thread(target=ask)
t2 = Thread(target=timing)
t1.start()
t2.start()
t1.join()
t2.join()
why this code is not running in parallel, it take 20 seconds to run it, which means it is running in sequence. Thank you for your help.
import time
from queue import Queue
from threading import Thread
start = time.time()
def f():
time.sleep(0.5)
print("yes")
return 'yes'
def do_stuff(q):
while True:
output = q.get()
q.task_done()
q = Queue(maxsize=100)
for message_nbr in range(40):
q.put(f())
num_threads = 10
for i in range(num_threads):
worker = Thread(target=do_stuff, args=(q, ))
worker.setDaemon(True)
worker.start()
q.join()
print("time: ", time.time() - start) # ~20 seconds
The answer lies here:
for message_nbr in range(40):
q.put(f())
You're putting 40 instances of None into your queue, because you're calling f() which returns None instead of passing f (the function object) in. This block is what is taking 20 seconds to run!
Changing this code
def do_stuff(q):
while True:
output = q.get()
q.task_done()
to this
def do_stuff(q):
while True:
output = q.get()
output()
q.task_done()
is also necessary (you need to call the function!)
Final:
import time
from queue import Queue
from threading import Thread
start = time.time()
def f():
time.sleep(0.5)
print("yes")
return 'yes'
def do_stuff(q):
while True:
output = q.get()
output()
q.task_done()
q = Queue(maxsize=100)
for message_nbr in range(40):
q.put(f)
num_threads = 10
for i in range(num_threads):
worker = Thread(target=do_stuff, args=(q, ))
worker.setDaemon(True)
worker.start()
q.join()
print("time: ", time.time() - start) # time: 2.183439254760742
this one works !
start = time.time()
def f(m):
time.sleep(0.5)
print("yes")
return 'yes'
def do_stuff(q):
while True:
output = q.get()
final_result = f(output)
q.task_done()
q = Queue(maxsize=0)
for message_nbr in range(10):
# q.put(f())
q.put(message_nbr)
num_threads = 10
for i in range(num_threads):
worker = Thread(target=do_stuff, args=(q, ))
worker.setDaemon(True)
worker.start()
q.join()
print("time: ", time.time() - start)
Can anyone please give me a small and simple example on how to use threading with pyserial communication.
I am googling for over three days and I am still illeterate and I dont even have a working piece of code which integrate both of them
Basically I am aiming to use threading in this scenario:
Have a serial communication continuously go on in the back ground to attain certain value (say A) from an MCU.
Stop attaining value A - then attain value B...and start continuously attaining value A again.
You can find some basic code here.
import threading
import time
import sys
import serial
import os
import time
def Task1(ser):
while 1:
print "Inside Thread 1"
ser.write('\x5A\x03\x02\x02\x02\x09') # Byte ArrayTo Control a MicroProcessing Unit
b = ser.read(7)
print b.encode('hex')
print "Thread 1 still going on"
time.sleep(1)
def Task2(ser):
print "Inside Thread 2"
print "I stopped Task 1 to start and execute Thread 2"
ser.write('x5A\x03\x02\x08\x02\x0F')
c = ser.read(7)
print c.encode('hex')
print "Thread 2 complete"
def Main():
ser = serial.Serial(3, 11520)
t1 = threading.Thread(target = Task1, args=[ser])
t2 = threading.Thread(target = Task2, args=[ser])
print "Starting Thread 1"
t1.start()
print "Starting Thread 2"
t2.start()
print "=== exiting ==="
ser.close()
if __name__ == '__main__':
Main()
There's no factual basis for the claim by Task2:
print "I stopped Task 1 to start and execute Thread 2"
Your implementation starts one thread then immediately starts the other without stopping the first. This means that the ser.read and ser.write commands could interfere with each other.
The simplest thing you could do to address this is to introduce variables that allow communication:
import sys
import os
import time
import threading
thread_flag = None
def Report(s):
print s
sys.stdout.flush() # helps to ensure messages from different threads appear in the right order
def Stop():
global thread_flag
thread_flag = 'stop'
def Task1(ser):
Report("Inside Thread 1")
global thread_flag
thread_flag = 'go'
while True:
Report("Thread 1 waiting for permission to read")
while thread_flag != 'go': time.sleep( 0.001 )
while thread_flag == 'go':
Report("Thread 1 is reading")
#ser.write('\x5A\x03\x02\x02\x02\x09') # Byte ArrayTo Control a MicroProcessing Unit
#b = ser.read(7)
#Report(b.encode('hex'))
time.sleep(1)
if thread_flag == 'stop': break
else: thread_flag = 'paused' # signals that the inner loop is done
Report("Thread 1 complete")
def Task2(ser):
Report("Inside Thread 2")
global thread_flag
thread_flag = 'pause' # signals Task1 to pause
while thread_flag != 'paused': time.sleep(0.001) # waits for Task1 inner loop to exit
Report("I stopped Task 1 to start and execute Thread 2")
#ser.write('x5A\x03\x02\x08\x02\x0F')
#c = ser.read(7)
#Report(c.encode('hex'))
thread_flag = 'go' # signals Thread 1 to resume
Report("Thread 2 complete")
def Main():
ser = None # serial.Serial(3, 11520)
t1 = threading.Thread(target = Task1, args=[ser])
t2 = threading.Thread(target = Task2, args=[ser])
Report("Starting Thread 1")
t1.start()
time.sleep(3)
Report("Starting Thread 2")
t2.start()
if __name__ == '__main__':
Main()
That approach uses a global variable, which is often frowned upon. You could instead make Task1 and Task2 methods of an object self that carries both self.ser and self.thread_flag as attributes.
For any inter-thread communication more complex than this, you need to investigate locks, mutexes and semaphores (e.g. threading.Lock)