1

I am trying to take user input in Python with a timer. I want the user to only have 10 seconds to enter something. However when 10 seconds is over the message "Time up!" is printed but the script does not stop.

import pygame
from threading import Thread

clock = pygame.time.Clock()
timee = 0
UIn=None

def func1():
    global timee
    global clock
    global UIn
    while True:
        milli = clock.tick()
        seconds = milli/1000

        timee=timee+seconds
        if(int(timee)==10):
            print("Time is over")
            quit()
        

def func2():
    global UIn
    print("Working")
    input("Press key:\t")


Thread(target=func1).start()
Thread(target=func2).start()
UIn=input("Press key:\t")
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • I have answered a similar question in [this](https://stackoverflow.com/questions/68968373/how-to-wait-for-an-input-for-a-set-amount-of-time-in-python/68968440#68968440) link – Ofek Glick Oct 03 '21 at 13:48

2 Answers2

0

You can use the Timer class for this purpose

from threading import Timer

timeout = 10
t = Timer(timeout, print, ['Sorry, times up!'])
t.start()
prompt = "You have %d seconds to answer the question. What color do cherries have?...\n" % timeout
answer = input(prompt)
t.cancel()

Output:

You have 10 seconds to answer the question. What color do cherries have?
(After 10 seconds)
Sorry, times up!
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Maximilian Freitag
  • 939
  • 2
  • 10
  • 26
  • And of course use a if ... else statement for the correct answer. So ... if answer == "red": ... print("Correct") ... else: .... print("Try again") – Maximilian Freitag Oct 03 '21 at 14:11
  • 1
    Timer is a class, not a library. threading on the other hand is the library that contains it. – COOL_IRON Oct 03 '21 at 14:13
  • 1
    @COOL_IRON Thanks for the correction. I wanted to change and edit this but the site won't let me. – Maximilian Freitag Oct 03 '21 at 14:17
  • copy paste of [this thread](https://stackoverflow.com/a/15533404/12892026) .. ^^ – mnikley Oct 03 '21 at 14:18
  • 1
    The answer is not correct because the timer does not cancel the `input`. `Input` continues after the time is love. The question is how to "stop" `input` after 10 seconds. – Rabbid76 Oct 03 '21 at 14:19
  • @Rabbid76 yeah youre right, however the author mentioned that he does not want the script to stop, he might also mean the input by that – mnikley Oct 03 '21 at 14:21
  • 1
    @matle No he does not. For this he put `input` in a separate thread (`func2`). The goal is to "terminate" `func2`. Therefore the answer is wrong. – Rabbid76 Oct 03 '21 at 14:23
0

After giving it some thought and thanks to @Rabbid76 you probably want something like this (modified after the code from this great post):

import msvcrt
import time
import sys

class TimeoutExpired(Exception):
    pass

def input_with_timeout(prompt, timeout, timer=time.monotonic):
    """Timed input function, taken from https://stackoverflow.com/a/15533404/12892026"""
    sys.stdout.write(prompt)
    sys.stdout.flush()
    endtime = timer() + timeout
    result = []
    while timer() < endtime:
        if msvcrt.kbhit():
            result.append(msvcrt.getwche()) #XXX can it block on multibyte characters?
            if result[-1] == '\r':
                return ''.join(result[:-1])
        time.sleep(0.04) # just to yield to other processes/threads
    raise TimeoutExpired

# create a timed input object
try:
    answer = input_with_timeout("Give me an answer: ", 10)
except TimeoutExpired:
    print('\nSorry, times up')
else:
    print(f'\nYour answer was: {answer}')

# continue with code and verify the input
if answer:
    if answer == "yes":
        print("OK")
mnikley
  • 1,625
  • 1
  • 8
  • 21