Using countdown timer to jump out of while loop Python - python

I'll just get to the code to show you, I'm trying to stop my while loop when my timer is over. Is there a way to do that?
from threading import Timer
def run(timeout=30, runs):
timer(timeout)
while runs > 0 or over():
#Do something
print "start looping"
def timer(time):
t = Timer(time, over)
print "timer started"
t.start()
def over():
print "returned false"
return False
As you can see, I'm trying to use the function over() to stop my while loop. Currently, when my time stop, over is returned as false, but it doesn't affect my while loop. I must be doing something wrong.
So what Timer object allows me to do is to pass a function param so that when the timer is over, it calls that function, over(). As over() returns False, it doesn't directly affect the while loop in real time. Will I need a callback to implicitly force the while to be false or is my method of stopping is completly faulty and will not work.

Changes
When your timer expires, you need to change the state so that when over is invoked, it will return True. Right now, I keep that in global state for simplicity. You will want to change this at some point.
Also, you had a logic error in your while loop condition. We need to make sure it still has runs and is not over.
#!/usr/bin/env python
from threading import Timer
globalIsOver = False
def run(runs, timeout=30):
timer(timeout)
while runs > 0 and not over():
#Do something
print "start looping"
print 'Exited run function.'
def timer(time):
t = Timer(time, setOver)
print "timer started"
t.start()
def setOver():
global globalIsOver
print '\nSetting globalIsOver = True'
globalIsOver = True
def over():
global globalIsOver
print 'returned = ' + str(globalIsOver)
return globalIsOver
run(100000000, timeout=2)
This returns the following after the 2 seconds have expired:
...
start looping
returned = False
start looping
returned = False
start looping
returned = False
Setting globalIsOver = True
start looping
returned = True
Exited run function.

Related

i wrote a code with python for hoop wiht computer but i can't end it when time up

hello i wrote a code with python for 'hoop' with computer and as long as it continues, the user loses
but i have a problem , I set a time limit for the input but after the time is up the program does not end, how i can fix it?
my code is :
from threading import Timer
print('Hello🙂\nLets plat hoop!!!!\nYou hvae 5 seconds for each turn! - Tyepe * instead of hoop! ')
hoop_cycle_lenght = int(input('Please insert cycle lenght (a number): '))
count = 0
while True:
count += 1
if count % 2 == 0 :
timer = Timer(5.0 , print , ['Sorry time up'])
timer.start()
user_chice = input('Your choice: ')
timer.cancel()
if count % hoop_cycle_lenght == 0 and count != 0:
if user_chice == '*':
pass
else:
print('You do mistake!\nGame over!!!')
break
else:
user_chice = int(user_chice)
if user_chice == count:
pass
else:
print('You do mistake!\nGame over!!!')
break
else:
if count % hoop_cycle_lenght == 0 and count != 0:
print('Computer choice: hoop!')
else:
print('Computer choice:' , count)
input() pauses the program and waits for the user input.
The best solution for this would probably be an extra thread that reads inputs and stores them in an instance variable. So the main thread can check it.
A bit like with key events in curses with getch() or probably a similar implementation in pygame.
You could encounter problems with print though, because print() is not threadsave.
Another solution is some kind of timeout that interrupts the input.
I wrote something like this after a lengthy search for a solution:
class TimeoutHelper(Thread):
'''
A helper class for the measurement of timeouts
The function that should have the timeout gets defined and handed over to the
constructor of this class. This function has to return two values. The first
has to be True or the returned value of the defined function and the second
Value has to be false or the error the defined function raises.
Then the timer() method of this class is called with the length of the timeout
in milliseconds and the Error that should be called when the timeout occurs.
e.g.:
def func():
try:
self.con.ping(reconnect=True)
return True, None
except pymysql.err.OperationalError as e:
return None, DBConnectionError(e)
timeout = TimeoutHelper(ping)
timeout.timer(self.config['timeoutMs'], DBTimeoutError)
The timer() method will return the first value returned from the defined function
if it is not None of False and raise the second value like an exception.
It will also raise the given error when the defined time is over.
Attributes
----------
daemon : bool
is true and makes the thread a daemon
func : function
the function given to the constructor
r : any
the value that gets returned by timer()
e : Exception
the exception that gets raised by timer()
Methods
-------
run():
Overwritten method that gets executed in the thread.
timer():
Handles the extra thread and measures the timeout.
'''
def __init__(self, func):
Thread.__init__(self)
self.daemon=True
self.func = func
self.r = None # values that are returned from func
self.e = None # errors from func
def run(self):
'''Call the given func.'''
self.r, self.e = self.func()
def timer(self, timeout, timeout_error):
'''
Starts the thread and measures the time for the timeout.
Returns the first returned value of func and raises the second value
as an exception.
Parameters:
timeout (int) : Timeout length in milliseconds.
timeout_error (Exception) : Exception that gets raised when
the timeout is exceeded.
'''
self.start()
t = timeout
while t > 0:
if self.e:
raise self.e
elif type(self.r) is not NoneType:
return self.r
else:
time.sleep(0.001)
t -= 1
else:
raise timeout_error
But I don't know if this works for said input() function.
You're structuring things a bit wrong.
running = True
def halt():
print("Your time has expired!")
running = False
timer = Timer(5.0, halt),
timer.start()
while running:
print("Running!")
... # Other things
print("Halting.")
The key points are that Timer needs to be started before your while loop, or you keep starting it. Secondly, you don't need cancel(). Doing so cancels whatever the timer would do when it would expire. Third, the function you call can do more than one thing, including setting the flag for your While loop to False, or go to another function entirely.
That said, it's unclear if treading.Timer() is really meant for this. Typically it's for handling threads, and that's not really what you're doing here. Typically in a game loop you do something like:
# Start a clock
# Loop around a set of player actions
# Check to see how much time has expired at certain checkpoints, quit if it's too much.
# Do something depending on the state when you leave the loop.

python timer for stopping a function

I want to build a function that will stop another function after a set time.
For example:
def start():
global bol_start
bol_start = True
timer()
if bol_start is True:
"do something until time is over"
def stop():
global bol_start
bol_start = False
sys.exit(0)
def timer():
"code for actual timer" ?
I would like to let the user define the time x how long the tool should run start().
After the time is over it should call stop().
If you have a loop in the function, that runs continuously, the simplest mechanic would be to measure time every iteration:
import time
def run():
start = time.time()
stop_seconds = 10
while time.time() - start < stop_seconds:
# do something
If you don't have a loop or the function consists of time consuming operations, you would need to kill the function in the middle of execution like suggested here: Timeout on a function call

Best (pythonic) way to interrupt and cancel a function call in progress?

I want a function foo() to do a number of things in one thread, with waiting periods during which it periodically checks if another thread (the main script) has set a please_stop variable to True, in which case I want foo() to immediately return a value (e.g., False).
My initial attempt looks like this:
import time
please_stop = False
def wait( n ) :
'''
Wait n seconds and return True, unless some other process
sets please_stop to True (and then return False).
'''
global please_stop
for t in range (n) :
if please_stop :
please_stop = False
return False
else :
print t
time.sleep(1)
return True
def foo() :
'''
Do a number of things, with wait() calls in between.
'''
global please_stop
print 'doing first thing'
if not wait( 5 ) : return False
print 'doing second thing'
if not wait( 5 ) : return False
print 'doing third thing'
return True
foo()
It works as it should, but I find the if not wait( 5 ) : return False expressions very clunky. What would be the simplest / most elegant way to achieve this behavior, possibly allowing the use of a simple wait( 5 ) expression instead? Am I re-inventing the wheel, would something like interrupts do a better job here?
Thanks in advance.
Well, you can simplify the implementation of wait by using a threading.Event instead of a global variable:
import time
import threading
def wait(event, timeout):
if event.wait(timeout):
event.clear()
return False
else:
return True
def foo(event):
'''
Do a number of things, with wait() calls in between.
'''
print 'doing first thing'
if not wait(event, 5): return False
print 'doing second thing'
if not wait(event, 5): return False
print 'doing third thing'
return True
if __name__ == "__main__":
event = threading.Event()
t = threading.Thread(target=foo, args=(event,))
t.start()
time.sleep(6)
event.set()
Output:
doing first thing
doing second thing
But you're still using the if not wait(5) : return False pattern. To get rid of that, you'd need to throw an exception when the Event is set. You probably don't want the exception to escape from foo, though, so you need to either use a try/except block around the foo body, or use a context manager:
import time
import threading
from contextlib import contextmanager
class Interrupt(Exception): pass
def wait(event, timeout):
if event.wait(timeout):
event.clear()
raise Interrupt()
else:
return True
#contextmanager
def interruptible():
try:
yield
except Interrupt:
pass
def foo(event):
'''
Do a number of things, with wait() calls in between.
'''
with interruptible():
print 'doing first thing'
wait(event, 5)
print 'doing second thing'
wait(event, 5)
print 'doing third thing'
return True
return False # This will only be reached the main thread interrupts foo
This will behave exactly the same as the previous example, the only difference is instead of returning False to end foo, we raise an exception, which gets caught by the context manager, but causes us to skip the rest of the code inside of the context.

Implementing Timeout. Whats wrong with the following code?

The program prints Expired the first time. I am expecting the code to print "not expired" for atleast 4 times before printing expired. Can someone please explain the reason and help me correct the code. Thank you
import time
TIMEOUT = 5
class Timer ():
def __init__(self):
self.timeout = time.time()+TIMEOUT
def isExpired ():
return time.time() > self.timeout
timing = Timer()
def main():
while 1:
if timing.isExpired:
print "Expired"
return
else:
print "Not expired"
print "sleeping for 1 second"
time.sleep(1)
if __name__== "__main__":
main()
You have several problems:
You did not give your isExpired method a self argument. Define it as def isExpired(self):.
You are creating a new Timer instance on each loop iteration. Move the timing = Timer() outside the while loop.
timing.isExpired is a reference to the method object iself (which is always true in a boolean context). You need to do timing.isExpired() to actually call it.
These are all basic Python issues that have nothing to do with Timer. Read the Python tutorial to learn how to use classes and so on.
You are creating a Timer instance everytime. Take it away from loop, or your while loop is never going to terminate. Also, you need to call timing.isExpired as it is a method. So your code should be:
import time
TIMEOUT = 60 * 5
class Timer ():
def __init__(self):
self.timeout = time.time()+TIMEOUT
def isExpired (self):
return time.time() > self.timeout
def main():
timing = Timer()
while 1:
if timing.isExpired():
print "Expired"
return
else:
print "Not expired"
print "sleeping for 1 second"
time.sleep(1)

Is there an easy way in Python to wait until certain condition is true?

I need to wait in a script until a certain number of conditions become true?
I know I can roll my own eventing using condition variables and friends, but I don't want to go through all the trouble of implementing it, since some object property changes come from external thread in a wrapped C++ library (Boost.Python), so I can't just hijack __setattr__ in a class and put a condition variable there, which leaves me with either trying to create and signal a Python condition variable from C++, or wrap a native one and wait on it in Python, both of which sound fiddly, needlessly complicated and boring.
Is there an easier way to do it, barring continuous polling of the condition?
Ideally it would be along the lines of
res = wait_until(lambda: some_predicate, timeout)
if (not res):
print 'timed out'
Unfortunately the only possibility to meet your constraints is to periodically poll, e.g....:
import time
def wait_until(somepredicate, timeout, period=0.25, *args, **kwargs):
mustend = time.time() + timeout
while time.time() < mustend:
if somepredicate(*args, **kwargs): return True
time.sleep(period)
return False
or the like. This can be optimized in several ways if somepredicate can be decomposed (e.g. if it's known to be an and of several clauses, especially if some of the clauses are in turn subject to optimization by being detectable via threading.Events or whatever, etc, etc), but in the general terms you ask for, this inefficient approach is the only way out.
Another nice package is waiting - https://pypi.org/project/waiting/
install:
pip install waiting
Usage:
You pass a function that will be called every time as a condition, a timeout, and (this is useful) you can pass a description for the waiting, which will be displayed if you get TimeoutError.
using function:
from waiting import wait
def is_something_ready(something):
if something.ready():
return True
return False
# wait for something to be ready
something = # whatever
wait(lambda: is_something_ready(something), timeout_seconds=120, waiting_for="something to be ready")
# this code will only execute after "something" is ready
print("Done")
Note: the function must return a boolean - True when the wait is over, False otherwise
Here is another solution. The goal was to make threads to wait on each other before doing some work in a very precise order. The work can take unknown amount of time. Constant polling is not good for two reasons: it eats CPU time and action does not start immediately after condition is met.
class Waiter():
def __init__(self, init_value):
self.var = init_value
self.var_mutex = threading.Lock()
self.var_event = threading.Event()
def WaitUntil(self, v):
while True:
self.var_mutex.acquire()
if self.var == v:
self.var_mutex.release()
return # Done waiting
self.var_mutex.release()
self.var_event.wait(1) # Wait 1 sec
def Set(self, v):
self.var_mutex.acquire()
self.var = v
self.var_mutex.release()
self.var_event.set() # In case someone is waiting
self.var_event.clear()
And the way to test it
class TestWaiter():
def __init__(self):
self.waiter = Waiter(0)
threading.Thread(name='Thread0', target=self.Thread0).start()
threading.Thread(name='Thread1', target=self.Thread1).start()
threading.Thread(name='Thread2', target=self.Thread2).start()
def Thread0(self):
while True:
self.waiter.WaitUntil(0)
# Do some work
time.sleep(np.random.rand()*2)
self.waiter.Set(1)
def Thread1(self):
while True:
self.waiter.WaitUntil(1)
# Do some work
time.sleep(np.random.rand())
self.waiter.Set(2)
def Thread2(self):
while True:
self.waiter.WaitUntil(2)
# Do some work
time.sleep(np.random.rand()/10)
self.waiter.Set(0)
Waiter for multiprocessing:
import multiprocessing as mp
import ctypes
class WaiterMP():
def __init__(self, init_value, stop_value=-1):
self.var = mp.Value(ctypes.c_int, init_value)
self.stop_value = stop_value
self.event = mp.Event()
def Terminate(self):
self.Set(self.stop_value)
def Restart(self):
self.var.value = self.init_value
def WaitUntil(self, v):
while True:
if self.var.value == v or self.var.value == self.stop_value:
return
# Wait 1 sec and check aiagn (in case event was missed)
self.event.wait(1)
def Set(self, v):
exit = self.var.value == self.stop_value
if not exit: # Do not set var if threads are exiting
self.var.value = v
self.event.set() # In case someone is waiting
self.event.clear()
Please comment if this is still not the best solution.
You've basically answered your own question: no.
Since you're dealing with external libraries in boost.python, which may change objects at their leisure, you need to either have those routines call an event handler refresh, or work with a condition.
Here is the threading extention to Alex's solution:
import time
import threading
# based on https://stackoverflow.com/a/2785908/1056345
def wait_until(somepredicate, timeout, period=0.25, *args, **kwargs):
must_end = time.time() + timeout
while time.time() < must_end:
if somepredicate(*args, **kwargs):
return True
time.sleep(period)
return False
def wait_until_par(*args, **kwargs):
t = threading.Thread(target=wait_until, args=args, kwargs=kwargs)
t.start()
print ('wait_until_par exits, thread runs in background')
def test():
print('test')
wait_until_par(test, 5)
From the computational perspective there must be a check for all conditions somewhere, sometime. If you have two parts of code, one that generates conditions changes and the other one that should be executed when some are true, you can do the following:
Have the code that changes conditions in, say, main thread, and the code that should be launched when some conditions are true, in a worker thread.
from threading import Thread,Event
locker = Event()
def WhenSomeTrue(locker):
locker.clear() # To prevent looping, see manual, link below
locker.wait(2.0) # Suspend the thread until woken up, or 2s timeout is reached
if not locker.is_set(): # when is_set() false, means timeout was reached
print('TIMEOUT')
else:
#
# Code when some conditions are true
#
worker_thread = Thread(target=WhenSomeTrue, args=(locker,))
worker_thread.start()
cond1 = False
cond2 = False
cond3 = False
def evaluate():
true_conditions = 0
for i in range(1,4):
if globals()["cond"+str(i)]: #access a global condition variable one by one
true_conditions += 1 #increment at each true value
if true_conditions > 1:
locker.set() # Resume the worker thread executing the else branch
#Or just if true_conditions > 1: locker.set();
#true_conditions would need be incremented when 'True' is written to any of those variables
#
# some condition change code
#
evaluate()
For more information concerning this method, visit: https://docs.python.org/3/library/threading.html#event-objects
Proposed solution:
def wait_until(delegate, timeout: int):
end = time.time() + timeout
while time.time() < end:
if delegate():
return True
else:
time.sleep(0.1)
return False
Usage:
wait_until(lambda: True, 2)
I once used this in my code:
while not condition:
pass
Hope this helps
In 2022 now you could use https://trio-util.readthedocs.io/en/latest/#trio_util.AsyncValue
I think this comes closest to what you want in its "smoothest" form
This worked for me
direction = ''
t = 0
while direction == '' and t <= 1:
sleep(0.1)
t += 0.1
This is for waiting for a signal while making sure time limit of 1 second
here's how:
import time
i = false
while i == false:
if (condition):
i = true
break
Here's my Code I used during one of my Projects :
import time
def no() :
if (Condition !!!) :
it got true
oh()
else:
time.sleep(1) /Don't remove or don't blame me if ur system gets ""DEAD""
no()
def oh() : /Ur main program
while True:
if(bla) :
.......
no()
else :
time.sleep(1)
oh()
oh()
Hope it Helps

Categories

Resources