# How to set input time limit for user in game?

**URL:** <https://discuss.python.org/t/how-to-set-input-time-limit-for-user-in-game/21610>\
**Category:** Python Help\
**Tags:** help\
**Created:** [December 2, 2022, 10:11pm UTC](https://discuss.python.org/t/how-to-set-input-time-limit-for-user-in-game/21610 "2022-12-02T22:11:18Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Pamix](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/pamix/32/10038_2.png) [@Pamix](https://discuss.python.org/u/Pamix)\
**Post date:** [December 2, 2022, 10:11pm UTC](https://discuss.python.org/t/how-to-set-input-time-limit-for-user-in-game/21610/1 "2022-12-02T22:11:18Z")

</div>

I was wondering how I can make a program with input of MAXIMUM 5 seconds(e.g he can send input after 2 seconds) in python I decided to do a SIMPLE game where you basically have to rewrite a word below 5 seconds. I know how to create input and make it wait EXACTLY 5 SECONDS, but what I want to achieve is to set maximum time of input to 5 seconds so if a user types an answer in let’s say 2 seconds he will go the next word. Could you tell me the way to achieve my goal. Thanks in advance!(I might respond the next day in case of getting an answer because I have to go sleep)

The code I have right now

```python
for word in ["banana","earth","turtle","manchester","coctail","chicken"]:

    # User gets maximum of 5 seconds to write the word,
    # if he does it before 5 seconds pass ,he goes to next word (does not have to wait exactly 5 seconds, he   
    # can send input in e.g 2 seconds)      
    # if he does not do it in 5 seconds he loses game and it is finished

    user_input = input(f"Type word '{word}': ")

    #IF the word is correct go to next iteration
    if(user_input==word):
        continue

    #If the word is incorrect finish the game
    else:
        print("You lost")
        break

```

# I tried to do it with threading.Timer() but it doesn’t work

```python
import threading

class NoTime(Exception):
    pass

def count_time():
    raise NoTime

for word in ["banana","earth","turtle","manchester","coctail","chicken"]:
    try:

        #Create timer which raises exception after 5 seconds
        timer = threading.Timer(5,count_time)
        timer.start()

        user_input = input(f"Type word '{word}': ")
        #if timer hasn't lasted 5 seconds then destroy it in order to prevent unwanted exception
        timer.cancel()

        if user_input==word:
            print("Correct")
        else:
            print("Incorrect, you LOSE!")
            break

    except NoTime:
        print("You run out of time, you lose")
        break

```

# The error i get

```python
Traceback (most recent call last):
  File "C:\Users\papit\AppData\Local\Programs\Python\Python311\Lib\threading.py", line 1038, in _bootstrap_inner
    self.run()
  File "C:\Users\papit\AppData\Local\Programs\Python\Python311\Lib\threading.py", line 1394, in run
    self.function(*self.args, **self.kwargs)
  File "C:\Users\papit\OneDrive\Pulpit\Programming\Python Bro Course\Math\second\threading_training.py", line 7, in count_time
    raise NoTime
NoTime

```

---

<div class="post-metadata">

**Author:** ![barry-scott](https://avatars.discourse-cdn.com/v4/letter/b/e9c0ed/32.png) [@barry-scott](https://discuss.python.org/u/barry-scott)\
**Post date:** [December 2, 2022, 11:28pm UTC](https://discuss.python.org/t/how-to-set-input-time-limit-for-user-in-game/21610/2 "2022-12-02T23:28:09Z")

</div>

There are two ways I can think of.

1. Use the signal.alarm() function
2. Use non-blcking I/O

For (1) - untested!  
a) Set up a signal handler for the SIGALARM signal.  
b) in a try block call signal.alarm() then input()  
c) If the input completes cancel the signal.alarm()  
d) if the SIGALARM fires you can ignore the signal and  
catch the I/O expection from input()

For (2) - also untested!  
Use the select function from the select module.  
Set the sys.stdin.fileno() to be non\_blocking.  
Then you can call select on sys.stdin.fileno() (== 1) with a timeout.  
When select returns check to see if ther are a timeout of the stdin is readable.  
To read what the user typed call os.read().  
That will allow you to read a line once its typed.  
If you use the termio module you can set it up so that the terminal to can be  
reading 1 char at a time without blocking.

---

<div class="post-metadata">

**Author:** ![cameron](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/cameron/32/2658_2.png) [@cameron](https://discuss.python.org/u/cameron)\
**Post date:** [December 2, 2022, 11:35pm UTC](https://discuss.python.org/t/how-to-set-input-time-limit-for-user-in-game/21610/3 "2022-12-02T23:35:22Z")

</div>

> I was wondering how I can make a program with input of MAXIMUM 5  
> seconds(e.g he can send input after 2 seconds) in python I decided to  
> do a SIMPLE game where you basically have to rewrite a word below 5  
> seconds. I know how to create input and make it wait EXACTLY 5 SECONDS,

Do you? How would you do that?

> but what I want to achieve is to set maximum time of input to 5 seconds  
> so if a user types an answer in let’s say 2 seconds he will go the next  
> word. Could you tell me the way to achieve my goal. Thanks in  
> advance!  
> (I might respond the next day in case of getting an answer because I  
> have to go sleep)

That’s fine, we’re all in different timezones here.

> The code I have right now

```
 import threading

 class NoTime(Exception):
     pass

 def count_time():
     raise NoTime

 for word in ["banana","earth","turtle","manchester","coctail","chicken"]:
     try:
         #Create timer which raises exception after 5 seconds
         timer = threading.Timer(5,count_time)
         timer.start()
         user_input = input(f"Type word '{word}': ")
         #if timer hasn't lasted 5 seconds then destroy it in order to prevent unwanted exception
         timer.cancel()

```

All this is fine so far. Except for the `try`/`except`.

```
         if user_input==word:
             print("Correct")
         else:
             print("Incorrect, you LOSE!")
             break
     except NoTime:
         print("You run out of time, you lose")
         break

```

The difficulty is that the `Timer` runs in a separate `Thread`, so when  
it raises an exception that exception unwinds the separate `Thread`’s  
stack, not your main programme stack.

> # The error i get
> 
> ```auto
> Traceback (most recent call last):
> File "C:\Users\papit\AppData\Local\Programs\Python\Python311\Lib\threading.py", line 1038, in _bootstrap_inner
> self.run()
> File "C:\Users\papit\AppData\Local\Programs\Python\Python311\Lib\threading.py", line 1394, in run
> self.function(*self.args, **self.kwargs)
> File "C:\Users\papit\OneDrive\Pulpit\Programming\Python Bro Course\Math\second\threading_training.py", line 7, in count_time
> raise NoTime
> NoTime
> 
> ```

See that in this traceback, your main programme is not part of the call  
stack. Instead, `count_time` is called directly from the threading  
library. This is characteristic of the code being run in its own thread.

Basicly, you can’t interrupt a `Thread`. The best you get to do is to  
set variables and poll them, or run parallel things in Threads and  
collect their results.

What you could do is:

- make a `Queue`
- run the `input()` in its own Thread, and have it `put` the input  
result to the Queue
- kick off a `Timer` to put a distinctive value such as `None` onto the  
`Queue`

The main programme reads from the queue: whichever happens first (the  
`input` or the timer) will be the first value you `get` from the  
`Queue`. Cancel the timer. Test the value.

This does still leave the `input` blocking, which can be a problem for  
further input.

Cheers,  
Cameron Simpson [cs@cskk.id.au](mailto:cs@cskk.id.au)

---

<div class="post-metadata">

**Author:** ![tjreedy](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/tjreedy/32/137_2.png) [@tjreedy](https://discuss.python.org/u/tjreedy)\
**Post date:** [December 3, 2022, 7:37am UTC](https://discuss.python.org/t/how-to-set-input-time-limit-for-user-in-game/21610/4 "2022-12-03T07:37:57Z")

</div>

One possibility is to use a prebuilt event loop with time-delay callbacks: 1) tkinter and ‘after’ functions; asyncio and call\_later functions. There are likely solutions to using either on stackoverflow. IDLE uses tkinter after functions to display completions and call hints after a delay.

---

<div class="post-metadata">

**Author:** ![Pamix](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/pamix/32/10038_2.png) [@Pamix](https://discuss.python.org/u/Pamix)\
**Post date:** [December 3, 2022, 11:13pm UTC](https://discuss.python.org/t/how-to-set-input-time-limit-for-user-in-game/21610/5 "2022-12-03T23:13:53Z")

</div>

Hi, thanks for answer, unfortunatelety I haven’t succeeded in finding solution yet. I read something about signal.alarm() and it turned out that it doesn’t work on windows. I haven’t tried your second advice yet because I have to learn these things and it takes some time. I will give myself few days to solve that problem and If i don’t manage to do it I will seek for more help.

---

<div class="post-metadata">

**Author:** ![Pamix](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/pamix/32/10038_2.png) [@Pamix](https://discuss.python.org/u/Pamix)\
**Post date:** [December 3, 2022, 11:21pm UTC](https://discuss.python.org/t/how-to-set-input-time-limit-for-user-in-game/21610/6 "2022-12-03T23:21:20Z")

</div>

Thanks for answer, I haven’t tried tkinter solution yet(of course I will do it but I don’t think that i can use tkinter module to structure my console program), I learned something about asyncio but not enough to solve that problem. I will try to solve that problem in few days and if I don’t succeed i will look for more help.

---

<div class="post-metadata">

**Author:** ![Pamix](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/pamix/32/10038_2.png) [@Pamix](https://discuss.python.org/u/Pamix)\
**Post date:** [December 3, 2022, 11:23pm UTC](https://discuss.python.org/t/how-to-set-input-time-limit-for-user-in-game/21610/7 "2022-12-03T23:23:48Z")

</div>

Hi, thanks for answer but in your solution you say that “_This does still leave the input blocking, which canbe a problem for further input._” and that’s the main problem because I wanted to throw an exception in order to get rid of that input.

---

<div class="post-metadata">

**Author:** ![tjreedy](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/tjreedy/32/137_2.png) [@tjreedy](https://discuss.python.org/u/tjreedy)\
**Post date:** [December 4, 2022, 1:59am UTC](https://discuss.python.org/t/how-to-set-input-time-limit-for-user-in-game/21610/8 "2022-12-04T01:59:08Z")

</div>

I realized that the blocking nature of input() is a problem for using event loops. This 50+ years old tech is not meant for timeout interaction. But stackoverflow searh for `[python] input timeout` has multiple answers.

> **[Human verification](https://stackoverflow.com/nocaptcha?s=1369d771-48e2-48b0-bca2-cada57d1bff3)**
>
> Stack Overflow | The World’s Largest Online Community for Developers

The first hit [python - Keyboard input with timeout? - Stack Overflow](https://stackoverflow.com/questions/1335507/keyboard-input-with-timeout)  
has multiple answers for both unix and windows. We don’t need to add more answers here.

That said, are you required to use a console/terminal? In a tkinter app, one can display a label `type xyz` and a _non-blocking_ entry box `[]` and start a timer. If the entry event occurs first, stop the timer, else remove the entry box.

---

<div class="post-metadata">

**Author:** ![cameron](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/cameron/32/2658_2.png) [@cameron](https://discuss.python.org/u/cameron)\
**Post date:** [December 4, 2022, 5:05am UTC](https://discuss.python.org/t/how-to-set-input-time-limit-for-user-in-game/21610/9 "2022-12-04T05:05:31Z")

</div>

Aye.

Since you’re on a console it looks like Barry’s second suggestion is the  
most feasible:

- make the input nonblocking
- do a timedout read of some kind

Basicly you need to write an `input()`-like function which embodies a  
timeout.

Since you’re on Windows the `termios` base solutions probably won’t be  
available to you as it is a UNIX specific API. Basicly, you need a  
Windows supported read-with-timeout function of some kind which works in  
the console. I believe there’s more than one kind of Windows console  
these days, the ancient `cmd.exe` and the modern and I gather quite good  
Windows Terminal. You might do better with the latter, but I don’t know.

Cheers,  
Cameron Simpson [cs@cskk.id.au](mailto:cs@cskk.id.au)
