How to use Threading timers in a while loop - python

What I need help with.
The only reason I used 2 seconds was to delay the messages but I am using a while loop: now since the for loop: did not really work the timer delay does not seem to be working for some reason regardless of what I do. I don't want to use time.sleep() since it would delay the loops in the future I plan to add multiple threads. It seems easy I think the threading module is very bug or at least it does not work the way a person might expect from it but if anyone is experienced with this module it would be a big help. I am sure the answer is simple but I am an idiot that is why I can not figure it out.
from threading import Timer
isint = True
while (isint):
x =input("How many 'somethings' : ")
try:
x =int(x)
isint=False
except ValueError:
print("Type in a number.")
def something():
global x
if x > 0:
print('Something')
x = x-1
else:
pass
while True:
Timer(10 , something).start()

You should use different value for every Timer
Timer(10, ...)
Timer(12, ...)
Timer(14, ...)
And with loop
for i in range(x):
Timer(10 + i*2, something).start()
and every timer will start 2 seconds later after previous timer without using sleep()

Related

Is there a way to cancel an input() in Python 3.8 after a certain period of time? [duplicate]

This question already has answers here:
Keyboard input with timeout?
(28 answers)
Closed 2 years ago.
I'm writing a program in Python 3.8. I'd like to make an input, let's say variable v. If v is input as "n," then some code is run. Any other input does nothing. Additionally, if the time runs out and nothing is inputted for v, then the "n" code is run.
I've tried a couple of different timers which work alright, but I'm struggling on how to cancel the input, since it stops my whole program and won't proceed onto the code I want to run.
Here's what I have:
def timerMethod():
timeout = 10
t = Timer(timeout, print, ['Sorry, times up'])
t.start()
prompt = "You have %d seconds to choose: are you feeling ok? y/n: \n" % timeout
answer = input(prompt)
if (answer == "n"):
feelingBad = True
t.cancel()
The two problems that I've encountered are 1. feelingBad (global variable) will never be made true. I feel like this is a basic Py principle that I've forgotten here, and I can change the way the code is written here, but if you'd like to point out my error please do. The main problem 2. is that if there is no input for the answer variable, the timer will end but the program will not proceed. If someone could please help me on the right track as on how to cancel the input prompt when the timer runs out, I'd greatly appreciate it.
Check the multithreading
here. I wish there was a better explanation on how it works. In my own words, one thread starts and sets the start time which is taken up by the second. Instead of a timer that counts down, it runs an if statement which compares the time taken with the time limit, which gives a space for any code to be run before the program exits.
You can try this:
import time
from threading import Thread
user = None
def timeout():
cpt = 0
while user == None:
time.sleep(1); cpt += 1
if user != None:
return
if cpt == 10:
break
print("Pass")
Thread(target = timeout).start()
user = input()

Python: display dynamic information on user input

I would like to be able to receive command line input from user in a python script, and at the same time display to the user some dynamic information.
The user should be able to enter text, but this should not block the displaying of information.
My goal is to create a game, where I show users a countdown while they still have time to enter an answer.
Is this achievable?
Yeah. To create a countdown in the console, you could do something like this:
from time import sleep
for num in reversed(range(0,11)):
print(num)
sleep(1.0)
or
from time import sleep
time = 10
while time != 0:
print(time)
time = time - 1
sleep(1.0)
Either will countdown from 10 to 0 with a second in between each number. Since you might want the user to be able to enter answers as quickly or slowly as like before reaching 0... you might want to look into running two loops concurrently. this thread might be helpful for that. You'll want to figure out how to break out of both loops if the user gets the right answer (and have something come up that says they got the right answer) or if the user runs out of time.
Well sounded like an interesting thing to look into so I did, ran into a few problems pretty soon.
First, I was able to make a running counter but the problem is, since it is a loop, the next layer the counter loop will reset everything you've answered on the previous layer unless you've pressed enter to input answer(answer + enter , during that 1 second period).
if you are making reflex based thing that you only need to press single keys you might be able to succeed with my code by using module getch.
There were few modules that I could use for making the timer and program run at the same time, threading and multiprocessing(better results with threading).
It's basically a working thing if you just remove the counter function which adds the loop, but you won't see the timer.
Pygame might be a good thing to do this with, haven't used it myself but I'd presume so.
here is my code
import time
import threading
import os
timel = 5
def question():
q = input("",)
print(q)
if q == "2":
print("\nCorrect")
else:
exit("\nFalse, You lose!!")
def counter():
timel = 5
for i in range(0, timel):
print("How much is 1+1?", timel)
timel -= 1
time.sleep(1)
os.system("cls")
def timer(seconds):
time.sleep(seconds)
exit("\nTIMES UP, You lose!!")
def exit(msg):
print(msg)
os._exit(1)
def main():
thread = threading.Thread(target=timer, args=(int("{}".format(timel)),))
thread2 = threading.Thread(target=counter)
thread.start()
thread2.start()
question()
if __name__ == "__main__":
main()

Python Multithreaded Messenger Simulation. Stuck on timerThread update. What do?

I have a piece of code that simulates a system of messengers (think post office or courier service) delivering letters in a multithreaded way. I want to add a way to manage my messengers "in the field" to increase the efficiency of my system.
tl;dr: How do I update my tens-to-hundreds of timerthreads so they wait longer before calling their function?
Here's what the code I've written so far is supposed to do in steps.
Someone asks for a letter
We check to see if there are any available messengers. If none, we say "oops, sorry. can't help you with that"
If at least one is available, we send the messenger to deliver the letter (new timer thread with its wait param as the time it takes to get there and back)
When the messenger gets back, we put him in the back of the line of available messengers to wait for the next delivery
I do this by removing Messenger objects from a double ended queue, and then adding them back in after a timerthread is done waiting. This is because my Messengers are all unique and eventually I want to track how many deliveries each has had, how far they have traveled, and other stuff.
Here's a pseudoish-codesnippet of the larger program I wrote for this
numMessengers=5
messengerDeque=deque()
pOrder=0.0001
class Messenger:
def __init__(self):
for i in range(numMessengers):
messenger=Messenger()
messengerDeque.append(messenger)
def popDeque():
messenger=idleDeque.popleft()
print 'messenger #?, sent'
return messenger
def appendDeque(messenger):
print 'messenger #?, returned'
messengerDeque.append(messenger)
def randomDelivery():
if numpy.random.randint(0,10000)<=(pOrder*10000):
if len(messengerDeque)!=0:
messenger=popDeque()
tripTime=distance/speed*120
t=threading.Timer(tripTime,appendDeque,args=[messenger])
t.start()
else:
print "oops, sorry. can't help you with that"
The above works in my program.
What I would like to add is some way to 'reroute' my messengers with new orders.
Lets say you have to deliver a letter within an hour of when you get it. You have five messengers and five orders, so they're all busy. You then get a sixth order.
Messenger 2 will be back in 20 minutes, and order six will take 30 minutes to get to the delivery destination. So instead of saying "oops, we can't help you". We would say, ok, Messenger 2, when you get back, immediately go deliver letter six.
With the code I've written, I think this could be done by checking the active threads to see how long until they call their functions, pick the first one you see where that time + how long your new delivery takes is < 1 hr, cancel it, and start a new thread with the time left plus the new time to wait.
I just don't know how to do that.
How do you check how long is left in a timerthread and update it without making a huge mess of your threads?
I'm also open to other, smarter ways of doing what I described.
YAY PYTHON MULTITHREADING!!!!!
Thanks for the help
Using the class threading.Timer wont fulfill your needs. Although there is a "interval" member in Timer instances, once the Timer(thread) started running any changes in interval (time-out) are not considered.
Furthermore you need to know how much time is still left for the timer to be triggered, for which there isn't a method as far as I know.
Furthermore you probably also need a way to identify which Timer instance you need to update with the new timeout value, but this is up-to you.
You should implement your own Timer class, perhaps something along the lines of:
import threading
import time
class MyTimer(threading.Thread):
def __init__(self, timeout, event):
super(MyTimer, self).__init__()
self.to = timeout
self.evt = event
def setTimeout(self, v):
self.end = time.time() + v
def run(self):
self.start = time.time()
self.end = time.time() + self.to
while self.end > time.time():
time.sleep(0) # instead of thread.yield
self.evt()
def getRemaining(self):
return self.end - time.time()
def hi(): print "hi"
T=MyTimer(20,hi)
T.start()
for i in range(10):
time.sleep(1)
# isAlive gives you True if the thread is running
print T.getRemaining(), T.isAlive()
T.setTimeout(1)
for i in range(3):
time.sleep(1)
print T.getRemaining(), T.isAlive()

print python counter of GPIO pin output at set intervals

I'm having a problem with a task i'm doing with an anemometer that works using a switch every revolution. The task is using a raspberry pi therefore the language is in python.
What I am trying to do is print a counter value every 10 seconds. However I don't want it to be a delay where nothing happens during the 10 second wait. Basically I want the number of times a switch is pressed in 10 seconds printed to me every 10 seconds.
Sorry if that was vague any extra info needed just ask.
While True:
stuff = dio.readU8(portB)
dio.write8(portA, stuff)
if stuff == 192:
print ('on')
else:
print ('off')
This is what it currently does simply constantly print its state either on or off I havn't yet implemented a counter as I am unsure the way it works in python and am wondering if it is similar to other languages i'm new to python I only usually use Java. The above code works even though values may look weird.
You could use the time module to watch the time, put it in at the end of the event catching code to see if 10+ seconds has passed.
something like...
import time
last_time = time.time()
#start of event catching loop
if time.time() - last_time >= 10
print buttonCountVariable
last_time = time.time()

Is there a possibility to modify the reruns per second of a while-loop? (Python) [duplicate]

This question already has answers here:
How do I ensure that a Python while-loop takes a particular amount of time to run?
(3 answers)
Closed 9 years ago.
I have the following problem: I need a program that runs every minute. I have managed to do this with python's time-module and an infinite while-loop. It looks like this:
while True:
time_now = tm.gmtime(tm.time())
min_now = time_now.tm_min
if min_now - min_then == 1 or min_now - min_then == -59:
min_then = min_now
......
The loop runs about 150.000 times a second and while I don't think that the general performance is harmed worthy of mention, I wonder if there are alternatives.
Can I modify the number of reruns of a while loop? Or does the algorithm (in assembler, machine code etc.) just jump back to the beginning when finished? Can I use something like a 'wait'-command and will that help?
Thanks for listening (and answering ;) ),
best wishes,
Max
EDIT:
A sleep-command indeed solved my problems. I forget to mention that the rerun must take place every full clock-minute. A sleep for 60 seconds wouldn't be satisfying, however, I used a way that Xi Huan's link mentioned: After the execution of a loop, I use sleep(59.9-time_now.tm_sec). That reduces the CPU usage to 1%. Excellent.
And: Thank you all for your help! I'd like to upvote you, but I don't have enough reputation :D sry
bye!
An easy way would be to sleep in the loop, e.g.
import time
while True:
# do some stuff
time.sleep(60) #sleeps for a minute
EDIT:
Also be aware that you will need to 'import time' for this to work. Also, if you wish to limit the number of times it loops, this could be useful. The example below will loop once per minute and will loop 10 times in total.
import time
for x in xrange(0, 10):
#do stuff
time.sleep(60)
A common way to do this is by calling time.sleep, which is essentially the 'wait' command you ask about. If you do:
while True:
time.sleep(60)
# do stuff
The loop will end up running approximately once every minute, plus however long the do stuff takes. There are caveats mentioned in the docs that this isn't guaranteed to be an exact wait time, so you probably still want to check the time at each iteration (depending how strict the 'once per minute' is).
use a time.sleep method:
import time
while True:
#do something
time.sleep(60)

Categories

Resources