Posts: 10
Threads: 2
Joined: Apr 2018
Hello, I am making a Python game where there is a sequence of letters, and you have to guess it right within a certain amount of time. However, once the player pushes enter, the code is reviewed. Unless, of course, the time runs out, in which case it just passes. Here is my current code:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
now = time.time()
limit = now + 15
while time.time() < limit:
r2 = raw_input ( "Commands:" )
pass
word2 = 'sddddwwdddx'
for i in range ( min ( len (r2), len (word2))):
if r2[i] ! = word2[i]:
errors + = 1
if errorlevel > = errors or errors = = 0 :
print "Your plane sucsessfully went through the course!"
else :
pass
|
However, the person could not press enter until the time is up, but since they don't know when time is up, they have to wait much longer. How could I make it so when you press enter, it exits out of the while loop, but also immediately ends the person's choice if the time is up?
Thank You.
Posts: 2,128
Threads: 11
Joined: May 2017
If seen this question one time before. The solution was a trick.
You can use signaling to enforce calling some function and
finally this function raises an TimeoutError which bubbles up.
The minimal implementation as a context manager:
1 2 3 4 5 6 7 8 9 10 11 |
class TimeOut:
def __init__( self , timeout):
self .timeout = timeout
self ._orig_handler = signal.signal(signal.SIGALRM, self ._timeout)
def __enter__( self ):
signal.alarm( self .timeout)
return self
def __exit__( self , * args):
signal.signal(signal.SIGALRM, self ._orig_handler)
def _timeout( self , * args):
raise TimeoutError
|
Using the context manager:
1 2 |
with TimeOut( 5 ):
input ( 'Answer in 5 seconds: ' )
|
Error: ---------------------------------------------------------------------------
TimeoutError Traceback (most recent call last)
<ipython-input-38-304f3fa31b18> in <module>()
1 with TimeOut(5):
----> 2 input('Answer in 5 seconds: ')
3
<ipython-input-32-8635f61b6ed0> in _timeout(self, *args)
9 signal.signal(signal.SIGALRM, self._orig_handler)
10 def _timeout(self, *args):
---> 11 raise TimeoutError
12
TimeoutError:
Now you have to catch the TimoutError Exception, which bubbles up:
1 2 3 4 5 |
with TimeOut( 5 ):
try :
input ( 'Answer in 5 seconds: ' )
except TimeoutError:
print ( '\nTime is up!' )
|
Output: Answer in 5 seconds:
Time is up!
Posts: 10
Threads: 2
Joined: Apr 2018
Apr-08-2018, 03:06 PM
(This post was last modified: Apr-08-2018, 03:07 PM by Tbot.)
What is the final code then?
When I run
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
class TimeOut:
def __init__( self , timeout):
self .timeout = timeout
self ._orig_handler = signal.signal(signal.SIGALRM, self ._timeout)
def __enter__( self ):
signal.alarm( self .timeout)
return self
def __exit__( self , * args):
signal.signal(signal.SIGALRM, self ._orig_handler)
def _timeout( self , * args):
raise TimeoutError
with TimeOut( 5 ):
try :
input ( 'Answer in 5 seconds: ' )
except TimeoutError:
print ( '\nTime is up!' )
|
I get:
Error: Traceback (most recent call last):
File "Untitled", line 13
with TimeOut(5):
File "Untitled", line 4, in __init__
self._orig_handler = signal.signal(signal.SIGALRM, self._timeout)
NameError: global name 'signal' is not defined
Posts: 2,128
Threads: 11
Joined: May 2017
You have to import signal. It's in the stdlib of python.
Posts: 10
Threads: 2
Joined: Apr 2018
Even still, I got this error:
Error: Traceback (most recent call last):
File "Untitled", line 15
with TimeOut(5):
File "Untitled", line 6, in __init__
self._orig_handler = signal.signal(signal.SIGALRM, self._timeout)
AttributeError: 'module' object has no attribute 'SIGALRM'
Posts: 3,458
Threads: 101
Joined: Sep 2016
Please show your code. Or double check that you didn't name any of your files signal.py , which would override the builtin module.
Per the docs, that should work: https://docs.python.org/3/library/signal.html#example Wrote:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import signal, os
def handler(signum, frame):
print ( 'Signal handler called with signal' , signum)
raise OSError( "Couldn't open device!" )
signal.signal(signal.SIGALRM, handler)
signal.alarm( 5 )
fd = os. open ( '/dev/ttyS0' , os.O_RDWR)
signal.alarm( 0 )
|
Posts: 10
Threads: 2
Joined: Apr 2018
Apr-10-2018, 12:09 AM
(This post was last modified: Apr-10-2018, 12:09 AM by Tbot.)
I do not have any docs named signal.py
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import signal
class TimeOut:
def __init__( self , timeout):
self .timeout = timeout
self ._orig_handler = signal.signal(signal.SIGALRM, self ._timeout)
def __enter__( self ):
signal.alarm( self .timeout)
return self
def __exit__( self , * args):
signal.signal(signal.SIGALRM, self ._orig_handler)
def _timeout( self , * args):
raise TimeoutError
with TimeOut( 5 ):
try :
input ( 'Answer in 5 seconds: ' )
except TimeoutError:
print ( '\nTime is up!' )
|
Posts: 3,458
Threads: 101
Joined: Sep 2016
Are you on Windows? SIGALRM only exists on Unix.
Posts: 2,128
Threads: 11
Joined: May 2017
Apr-10-2018, 08:16 AM
(This post was last modified: Apr-10-2018, 08:16 AM by DeaD_EyE.)
Yes, Windows does not have it.
There is also a solution with a Thread: https://stackoverflow.com/a/37648512/2817354
It looks a bit hackish.
He is using a Timer from threading to send the MainThread a KeyboardInterrupt.
Posts: 10
Threads: 2
Joined: Apr 2018
I am using Windows 8.1
Since I don't have SIGALRM, what should I do? Is there a Windows equivalent?
Thank You.
|