Is there a way to add a timer to a python programm? - python-3.x

Im not very good with programming but im currently doing a multiplication learning programm for my brother and was wandering if there is any way to do it, so that he has to answer after a certain ammoun of time or else he fails the question. Here is my Code:
import random
F = 1
while F==1:
x = random.randint(1,10)
y = random.randint(1,10)
Result = y*x
print(y,"*",x)
Input = int(input())
if Result == Input:
print("correct")
else:
print("Wrong, correct result:",Result)
I hope this is good enough. I would appreciate any help! Thank a lot in advande

You can use threading module to create a thread and assign timer to that thread, if the timer runs out that means the sub thread is dead now the program will respond you got late.
Here's the solution:
import random
from threading import Thread
from time import sleep
def timer():
sleep(10) # wait for 10 seconds once the question is asked
return True
if __name__ == '__main__':
while True:
x = random.randint(1, 10)
y = random.randint(1, 10)
Result = y * x
print(y, "*", x)
time = Thread(target=timer) # Creating sub thread for timer processing
time.start() # starting the thread
Input = int(input())
if not time.isAlive(): # checking whether the timer is alive
print('You got late, Failed')
break
else:
pass
if Result == Input:
print("correct")
else:
print("Wrong, correct result:", Result)
if you use time.sleep() method on your main thread your program will hung up and so do your system as well for the time being, so instead of doing that I created a new thread which works completely independent of your main thread and your system will not hung up.

You can define your own using the Python's time module.
For example:
def timer(t):#t must be the time of the timer in seconds
while t:
mins,sec=divmod(t,60)
timer = '{:02d}:{:02d}'.format(mins, secs)
print(timer, end='\r')
time.sleep(1)
t=t-1
print("Time's Up")

Related

How to exit ThreadPoolExecutor with statement immediately when a future is running

Coming from a .Net background I am trying to understand python multithreading using concurrent.futures.ThreadPoolExecutor and submit. I was trying to add a timeout to some code for a test but have realised I don't exactly understand some elements of what I'm trying to do. I have put some simplified code below. I would expect the method to return after around 5 seconds, when the call to concurrent.futures.wait(futures, return_when=FIRST_COMPLETED) completes. In fact it takes the full 10 seconds. I suspect it has to do with my understanding of the with statement as changing the code to thread_pool = concurrent.futures.ThreadPoolExecutor(max_workers=2) results in the behvaiour I would expect. Adding a call to the shutdown method doesn't do anything as all the futures are already running. Is there a way to exit out of the with statement immediately following the call to wait? I have tried using break and return but they have no effect. I am using python 3.10.8
from concurrent.futures import FIRST_COMPLETED
import threading
import concurrent
import time
def test_multiple_threads():
set_timeout_on_method()
print("Current Time =", datetime.now()) # Prints time N + 10
def set_timeout_on_method():
futures = []
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as thread_pool:
print("Current Time =", datetime.now()) # Prints time N
futures.append(thread_pool.submit(time.sleep, 5))
futures.append(thread_pool.submit(time.sleep, 10))
concurrent.futures.wait(futures, return_when=FIRST_COMPLETED)
print("Current Time =", datetime.now()) # Prints time N + 5
print("Current Time =", datetime.now()) # Prints time N + 10
AFAIK, there is no native way to terminate threads from ThreadPoolExecutor and it's supposedly not even a good idea, as described in existing answers (exhibit A, exhibit B).
It is possible to do this with processes in ProcessPoolExecutor, but even then the main process would apparently wait for all the processes that already started:
If wait is False then this method will return immediately and the
resources associated with the executor will be freed when all pending
futures are done executing. Regardless of the value of wait, the
entire Python program will not exit until all pending futures are done
executing.
This means that even though the "End #" would be printed after cca 5 seconds, the script would terminate after cca 20 seconds.
from concurrent.futures import FIRST_COMPLETED, ProcessPoolExecutor, wait
from datetime import datetime
from time import sleep
def multiple_processes():
print("Start #", datetime.now())
set_timeout_on_method()
print("End #", datetime.now())
def set_timeout_on_method():
futures = []
with ProcessPoolExecutor() as executor:
futures.append(executor.submit(sleep, 5))
futures.append(executor.submit(sleep, 10))
futures.append(executor.submit(sleep, 20))
print("Futures created #", datetime.now())
if wait(futures, return_when=FIRST_COMPLETED):
print("Shortest future completed #", datetime.now())
executor.shutdown(wait=False, cancel_futures=True)
if __name__ == "__main__":
multiple_processes()
With max_workers set to 1, the entire script would take cca 35 seconds because (to my surprise) the last future doesn't get cancelled, despite cancel_futures=True.
You could kill the workers, though. This would make the main process finish without delay:
...
with ProcessPoolExecutor(max_workers=1) as executor:
futures.append(executor.submit(sleep, 5))
futures.append(executor.submit(sleep, 10))
futures.append(executor.submit(sleep, 20))
print("Futures created #", datetime.now())
if wait(futures, return_when=FIRST_COMPLETED):
print("Shortest future completed #", datetime.now())
subprocesses = [p.pid for p in executor._processes.values()]
executor.shutdown(wait=False, cancel_futures=True)
for pid in subprocesses:
os.kill(pid, signal.SIGTERM)
...
Disclaimer: Please don't take this answer as an advice to whatever you are trying achieve. It's just a brainstorming based on your code.
The problem is that you can not cancel Future if it was already started:
Attempt to cancel the call. If the call is currently being executed or finished running and cannot be cancelled then the method will return False, otherwise the call will be cancelled and the method will return True.
To prove it I made the following changes:
from concurrent.futures import (
FIRST_COMPLETED,
ThreadPoolExecutor,
wait as futures_wait,
)
from time import sleep
from datetime import datetime
def test_multiple_threads():
set_timeout_on_method()
print("Current Time =", datetime.now()) # Prints time N + 10
def set_timeout_on_method():
with ThreadPoolExecutor(max_workers=2) as thread_pool:
print("Current Time =", datetime.now()) # Prints time N
futures = [thread_pool.submit(sleep, t) for t in (2, 10, 2, 100, 100, 100, 100, 100)]
futures_wait(futures, return_when=FIRST_COMPLETED)
print("Current Time =", datetime.now()) # Prints time N + 5
print([i.cancel() if not i.done() else "DONE" for i in futures])
print("Current Time =", datetime.now()) # Prints time N + 10
if __name__ == '__main__':
test_multiple_threads()
As you can see only three of tasks are done. ThreadPoolExecutor actually based on threading module and Thread in Python can't be stopped in some conventional way. Check this answer

How does Executor(max_workers=n).submit() work in a loop?

Running the code below, I noticed that executor.submit(printer, i) is called for each value of i in range(100) before even the first process finishes. However, since I have set max_workers=3, only three processes can run at a time. Say the program starts and processes for values zero through two are running; at this moment, what happens to the executor.submit(printer, i) called for values three through ninety-nine? And if the answer is "they're stored in memory", is there a way I can calculate how much memory each pending process might take?
import time
from concurrent.futures import ProcessPoolExecutor
def printer(i):
print(i)
end_time = time.time() + 1
while time.time() < end_time:
pass
if __name__ == "__main__":
with ProcessPoolExecutor(max_workers=3) as executor:
for i in range(100):
print(i)
executor.submit(printer, i)
Also, would it be the same if I were to use executor.map(printer, range(100)) instead of the loop?

how to stop a thread started by a timer, in main thread

I am trying to start a thread to listen to the incoming messages from a socket. so it contains an infinite loop. but when I try to close the gui, it hangs there, and does not close it. here is more simplified code without using any gui.
import threading,time,sys
def f(x):
while True:
time.sleep(0.5)
print(x)
timer = threading.Timer(0.1,f,("some text",) )
timer.start()
time.sleep(2)
print("time to stop")
sys.exit()
as you see the line sys.exit() won't end all threads (main thread and thread started by timer).
now I was wondering how to kill that specific thread which started by the timer.
thank you for your help
I finally find a solution for it. somehow we can use global variables to end an endless loop inside a thread, and therefore close it.
import threading,time
def f(x):
global z
while True:
time.sleep(0.5)
print(x)
if not z:
break
global z
z = True
timer = threading.Timer(0.1,f,("some text",) )
timer.start()
time.sleep(2)
print("time to stop")
z = False

why doesn't time passes the thread in python

I've created a code so at a certian time it has to display a message. I tried it with a counter and it worked, but when using "strftime" it doesn't work. Can any one explain what I did wrong.
Below you'll fine the code I used.
import datetime, threading, time
now = datetime.datetime.now()
def foo():
counter = 0
next_call = time.time()
while True:
#counter +=1
if(now.strftime("%H:%M:%S")>=("22:00:00")):
print("go to sleep")
time.sleep(30)
else:
print (datetime.datetime.now())
next_call = next_call+1;
time.sleep(next_call - time.time())
timerThread = threading.Thread(target=foo)
timerThread.start()
You never change the value of 'now'. Conseqeuently it is the fixed time at which you start running this program.
You need to update it inside the loop.

threading with input() and while-loop

I'm trying to learn/understand threading in python and found this.
I tried to use this with input() but it doesn't work the way I imagined.
import queue
import threading
def cin(el, q):
while input() != el:
print('no')
continue
q.put(el)
checks = ['one', 'two']
q = queue.Queue()
for el in checks:
t = threading.Thread(target = cin, args = (el, q))
t.daemon = True
t.start()
s = q.get()
print(s)
I'm trying to run two threads who each have a while loop to check if the input() from console matches with one of the elements from the list. If it doesn't it waits for the next input. What happens is that only 'one'-thread, so the first element in the list works. After a lot of trys 'two'-thread works but the other doesn't. Where is the mistake? Can only one thread use the input()? Is it not possible to run two while-loops at the same time?

Resources