1

I made a program in python that looks like this:

import time
y = "a"
x = 0
while x != 10 and y == "a":
    y = input("What is your name? ")
    time.sleep(1)
    x = x + 1
if y != "a":
    print("Hi " + y)
else:
    print("You took too long to answer...")

I know that there is a way of accomplishing the same thing at this question: Keyboard input with timeout in Python, but I would like to know why this is not working. No matter how long I wait it doesn't time out; it just sits there waiting for me to type something in. What have I done wrong? I am using python 3.3 on Win 7.

Community
  • 1
  • 1
user2218101
  • 135
  • 2
  • 5
  • 10
  • 2
    That's because input blocks, the rest of the program doesn't execute until it's done. – Benjamin Gruenbaum Dec 14 '13 at 23:52
  • The program blocks at `y = input("What is your name? ")` until the user presses enter. Your program has nothing to interrupt the `input` and cause it to terminate early. Look at the answers you linked to for possible solutions. – Tim Dec 14 '13 at 23:54
  • 1
    Benjamin is right. What exactly do you want to do? – aIKid Dec 14 '13 at 23:54
  • @alKid I am trying to request the input for 10 seconds. – user2218101 Dec 15 '13 at 02:02

2 Answers2

1

Input is blocking in python. Meaning time.sleep(1) line and all lines after only get executed after the input is received.

Ruslan Osipov
  • 5,655
  • 4
  • 29
  • 44
  • How can I fix it? @Ruslan Osipov – user2218101 Dec 15 '13 at 01:46
  • @user2218101 Use a solution described in the answer you provided: http://stackoverflow.com/questions/1335507/keyboard-input-with-timeout-in-python. – Ruslan Osipov Dec 15 '13 at 14:26
  • I know that that code works, but for me this is an exercise in varieties of implementation rather than one in functionality. Do you know if I can fix this? – user2218101 Dec 20 '13 at 00:14
  • @user2218101 Async programming is the only way you can achieve desired functionality - there's no way to "fix" the code you provided: the problem you are trying to solve has to be approached in a completely different way. flyer's answer or the link above are 2 of the few ways to do it. – Ruslan Osipov Dec 20 '13 at 19:14
1

There're two ways to achieve what you want:

  • Use thread
    Encapsulate the input() statement in a thread, join for a timeout and then kill the thread. However, it's not recommended. Refer to this question: Is there any way to kill a Thread in Python?
  • Use a non-blocking input()
    This is recommended. Use signal.

I implement what you need in a simple way based on this blog:

import signal

y = 'a'
x = 0

class AlarmException(Exception):
    pass

def alarm_handler(signum, frame):
    raise AlarmException

def my_input(prompt="What's your name? ", timeout=3):
    signal.signal(signal.SIGALRM, alarm_handler)
    signal.alarm(timeout)
    try:
        name = input(prompt)
        signal.alarm(0)
        return name
    except AlarmException:
        print('timeout......')
    signal.signal(signal.SIGALRM, signal.SIG_IGN)

    return

while x != 10 and y == 'a':
    y = my_input(timeout=3) or 'a'
    x += 1

if y != 'a':
    print('Hi %s' % (y,))
else:
    print('You took too long to answer.')
Community
  • 1
  • 1
flyer
  • 9,280
  • 11
  • 46
  • 62