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)
Related
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.
Say I have a long running python function that looks something like this?
import random
import time
from rx import Observable
def intns(x):
y = random.randint(5,10)
print(y)
print('begin')
time.sleep(y)
print('end')
return x
I want to be able to set a timeout of 1000ms.
So I'm dong something like, creating an observable and mapping it through the above intense calculation.
a = Observable.repeat(1).map(lambda x: intns(x))
Now for each value emitted, if it takes more than 1000ms I want to end the observable, as soon as I reach 1000ms using on_error or on_completed
a.timeout(1000).subscribe(lambda x: print(x), lambda x: print(x))
above statement does get timeout, and calls on_error, but it goes on to finish calculating the intense calculation and only then returns to the next statements. Is there a better way of doing this?
The last statement prints the following
8 # no of seconds to sleep
begin # begins sleeping, trying to emit the first value
Timeout # operation times out, and calls on_error
end # thread waits till the function ends
The idea is that if a particular function timesout, i want to be able to continue with my program, and ignore the result.
I was wondering if the intns function was done on a separate thread, I guess the main thread continues execution after timeout, but I still want to stop computing intns function on a thread, or kill it somehow.
The following is a class that can be called using with timeout() :
If the block under the code runs for longer than the specified time, a TimeoutError is raised.
import signal
class timeout:
# Default value is 1 second (1000ms)
def __init__(self, seconds=1, error_message='Timeout'):
self.seconds = seconds
self.error_message = error_message
def handle_timeout(self, signum, frame):
raise TimeoutError(self.error_message)
def __enter__(self):
signal.signal(signal.SIGALRM, self.handle_timeout)
signal.alarm(self.seconds)
def __exit__(self, type, value, traceback):
signal.alarm(0)
# example usage
with timeout() :
# infinite while loop so timeout is reached
while True :
pass
If I'm understanding your function, here's what your implementation would look like:
def intns(x):
y = random.randint(5,10)
print(y)
print('begin')
with timeout() :
time.sleep(y)
print('end')
return x
You can do this partially using threading
Although there's no specific way to kill a thread in python, you can implement a method to flag the thread to end.
This won't work if the thread is waiting on other resources (in your case, you simulated a "long" running code by a random wait)
See also
Is there any way to kill a Thread in Python?
This way it works:
import random
import time
import threading
import os
def intns(x):
y = random.randint(5,10)
print(y)
print('begin')
time.sleep(y)
print('end')
return x
thr = threading.Thread(target=intns, args=([10]), kwargs={})
thr.start()
st = time.clock();
while(thr.is_alive() == True):
if(time.clock() - st > 9):
os._exit(0)
Here's an example for timeout
import random
import time
import threading
_timeout = 0
def intns(loops=1):
print('begin')
processing = 0
for i in range(loops):
y = random.randint(5,10)
time.sleep(y)
if _timeout == 1:
print('timedout end')
return
print('keep processing')
return
# this will timeout
timeout_seconds = 10
loops = 10
# this will complete
#timeout_seconds = 30.0
#loops = 1
thr = threading.Thread(target=intns, args=([loops]), kwargs={})
thr.start()
st = time.clock();
while(thr.is_alive() == True):
if(time.clock() - st > timeout_seconds):
_timeout = 1
thr.join()
if _timeout == 0:
print ("completed")
else:
print ("timed-out")
You can use time.sleep() and make a while loop for time.clock()
this is my source code that executes function every 1 seconds
buy, it only executes one times.
In short, I want to get the # of line from the named pipe output every seconds
Is there any suggestion for this problem?
thank you for your help in advance
class Monitor:
def __init__(self, namedpipe, name):
self.namedpipe = namedpipe
self.name = name
self.count = 0
def run(self):
print self.name+" start run"
while True:
line = self.namedpipe.readline()
self.count = self.count+1
def getCost(self):
print "Hi"
while True:
line = monitor.readline()
line = line.strip()
if not line:
ans =raw_input('stop?')
if ans=='y': break
monitorList = open(line, 'r')
m = Monitor(monitorList, line)
thread.start_new_thread(m.run, ())
time.sleep(1)
threading.Timer(0.1, m.getCost).start()
With Threading.Timer, you have to restart the timer each time it has expired - so during the execution of the function called when the timer expires - m.getCost in your code - the timer has to be started again. You might want to define a wrapper function to do this work, to avoid polluting m.getCost() with timer stuff.
I have a question regarding the example posted below...
On my machine calcIt() function takes about 5 seconds to complete.
The same calcIt() function is called from inside of MyClass's callCalcIt() method.
Using while loop MyClass is "watching" for calcIt() function to finish.
Question: A while loop inside of calcIt() method prints out '...running' only once. Honestly I was expecting to see at least 'an infinite loop' type of behavior where '...running' would be printed thousand times per second. Observing a fact the while loop executes a print '...running' line only once makes me believe while loop watches very 'loosely' for calcIt()'s progress. If so, what other (other than while loop) approach should be used to make sure you get what you want: an instant feedback from calcIt() function?
def calcIt():
a=True
while a:
for i in range(25000000):
pass
a=False
return True
class MyClass(object):
def __init__(self):
super(MyClass, self).__init__()
def callCalcIt(self):
b=True
while b:
result=calcIt()
print '...running'
if result: b=False
print 0
calcIt()
print 1
c=MyClass()
c.callCalcIt()
print 2
EDITED LATER:
Posting a revised code with an implementation of solution suggested by Ebarr:
import threading
updateMe=[]
def calcIt():
a=True
while a:
for y in range(3):
for i in range(15000000):
pass
updateMe.append(1)
a=False
return True
class MyClass(object):
def __init__(self):
super(MyClass, self).__init__()
def callCalcIt(self):
thread = threading.Thread(target=calcIt)
thread.start()
print '\n...thread started'
while thread.is_alive():
if len(updateMe)==1: print '...stage 1'
if len(updateMe)==2: print '...stage 2'
if len(updateMe)==3: print '...stage 3'
def printUpdate(self):
print 'updateMe=', len(updateMe)
c=MyClass()
c.callCalcIt()
I'm not sure what you were expecting to happen, but the explanation is very simple. You are running a single threaded code. This means that all of the above will be executed in serial, so there will be no concurrency between the two while loops in your code.
What you appear to be asking is how to thread your code such that you can check the progress of a running function. If that is the case, you can turn calcIt into a thread.
import threading
class CalcIt(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
for i in range(25000000):
pass
You would then change callCalcIt to:
def callCalcIt(self):
thread = CalcIt()
thread.start()
while thread.is_alive():
print '...running'
Alternatively, you can make it simpler:
import threading
def calcIt():
for i in range(25000000):
pass
def callCalcIt():
thread = threading.Thread(target=calcIt)
thread.start()
while thread.is_alive():
print '...running'
callCalcIt()
I can come up with two ways of doing that, but both require some modification to the calcIt function.
Method 1, callbacks:
def calc_it(callback):
r = 25000000
for x in xrange(r+1):
if not (x % 1000):
callback(x, r) # report every 1000 ticks
class Monitor(object):
def print_status(self, x, r):
print "Done {0} out of {1}".format(x, r)
def call(self):
calc_it(self.print_status)
Method 2, generator:
def calc_it():
r = 25000000
for x in xrange(r+1):
if not (x % 1000): # report every 1000 ticks
yield x, r
class Monitor(object):
def call(self):
for x, r in calc_it():
print "Done {0} out of {1}".format(x, r)
(A side note: in neither case Monitor has to be a class, that's just for consistency with the original code.)
Not sure exactly what you are trying to accomplish, but you could possibly use my newly written generator state machine thingie. Like so:
from generatorstate import State
def calcIt():
while True:
for i in range(25000000):
pass
yield
tick = State(calcIt)
print 0
tick()
print 1
tick()
print 2
I've added a couple of examples, sneak a peek at those if you think it might be a fit.
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.