1

I am writing a program in python that accepts two inputs.

Once the user gives the first input, he gets 10 seconds to give the second input. If the user is able to provide the second value within those 10 seconds and presses the enter key, the timer stops and goes to the next part of the program.

Is there any functionality in python that allows me to provide an interrupt after the 10 seconds and stop accepting the second input. And if the second input is given, stop the timer.

Terry Jan Reedy
  • 18,414
  • 3
  • 40
  • 52
Bharath Suresh
  • 483
  • 2
  • 18
  • 2
    You will need to use a multi threaded solution for this – Alan Kavanagh May 26 '19 at 16:23
  • 2
    You might be able to do this using [timeout-decorator](https://pypi.org/project/timeout-decorator/) since this is a relatively simple requirement. – shriakhilc May 26 '19 at 16:32
  • 1
    The python-idle tag is about the IDLE editor and shell, not 'doing nothing'. Anyway, you can easily do what you want with a simple tkinter program using an Entry and a .after callback. – Terry Jan Reedy May 26 '19 at 20:19

1 Answers1

2

You can create a custom Timer class and start it in a diffrent thread. Once the timeout occurs (after 10 seconds), you can send a SIGINT signal back to the parent thread, which will raise the KeyboardInterrupt exception that we catch in the main() function. Otherwise you can stop the Timer, after user enters the second input in the right time, which will then stop the Timer thread. Further, we can check if the KeyboardInterrupt happened due to timeout or user action.

Note: While we are sending the signal to the main process, we also need to check, on which platform we are running the programm. See signal.CTRL_C_EVENT and signal.SIGINT.

Demo: https://repl.it/repls/StandardBuoyantProtools

Solution:

import time
import threading
import os
import signal


class Timer(threading.Thread):
    _timeout = False
    _timer = 0
    _stopped = False

    def __init__(self, delay):
        super(Timer, self).__init__()
        self.restart(delay)

    def is_timeout(self):
        return self._timeout

    def stop(self):
        self._stopped = True

    def restart(self, delay):
        self._stopped = False
        self._timer = time.time() + delay

    def run(self):

        while not self._stopped:
            time.sleep(0.1)
            if time.time() >= self._timer:
                break
        if not self._stopped:
            self._timeout = True

            # check os name
            if os.name == 'nt':
                # we are on Windows
                os.kill(os.getpid(), signal.CTRL_C_EVENT)
            else:
                # we are on a Posix/Unix (or very unlikely on java) system
                os.kill(os.getpid(), signal.SIGINT)


def main():
    first_input = input('First input:')

    delay = 10
    timer = Timer(delay)
    timer.daemon = True

    try:
        print('\nStarting the timer for the second input %r second(s)' % delay)
        timer.start()

        second_input = input('Second input:')

        print('\nWell done. Stopping the timer!\n')
        timer.stop()

        print('Input values: %r %r\n' % (first_input, second_input))

        # do your stuff here...

    except KeyboardInterrupt:
        if timer.is_timeout():
            print("\nTimeout!")
        else:
            print("\nUser interrupted the input")


main()