Input without stopping program

2019-08-19 07:27发布

问题:

I am trying to make a countdown timer that prints the time remaining, and when you input something, it prints what you inputted. My problem is I don't want to wait for the input, just keep running the timer. My incorrect code:

timer = 100
while True:
    print(timer)
    timer -= 1

    if input('> '):
        print('the output of input')

You could say I want to have the timer printing the time in the background.

回答1:

Here's a function that will timeout if no input is given:

import select
import sys

def timeout_input(timeout, prompt="", timeout_value=None):
    sys.stdout.write(prompt)
    sys.stdout.flush()
    ready, _, _ = select.select([sys.stdin], [], [], timeout)
    if ready:
        return sys.stdin.readline().rstrip('\n')
    else:
        sys.stdout.write('\n')
        sys.stdout.flush()
        return timeout_value

You can easily modify it so it shows the remaining time by changing the timeout value on select.select to 1, and looping timeout times.



回答2:

Standard input and standard output (accessed via input() and print()) are not a good choice for writing interactive asynchronous user interface (UI). Python support a few UIs via it's standard library. For example, curses is a text based user interface available on many POSIX systems. Here is an exmaple code for showing a countdown timer while accepting a number from the user:

import time
import curses


def get_number(seconds):
    def _get_number(stdscr):
        stdscr.clear()
        timeout = time.time() + seconds
        s = ""
        while time.time() <= timeout:
            time_left = int(timeout - time.time())
            stdscr.addstr(0, 0, 'Countdown: {} {}'.format(time_left,
                                                          "*" * time_left + " " * seconds))
            stdscr.addstr(2, 0, ' ' * 50)
            stdscr.addstr(2, 0, 'Your Input: {}'.format(s))
            stdscr.refresh()
            stdscr.timeout(100)
            code = stdscr.getch()
            stdscr.addstr(10, 0, 'Code: {}'.format(code))  # for debug only
            stdscr.refresh()
            if ord("0") <= code <= ord("9"):
                s += chr(code)
                continue

            if code == 10 and s:  # newline
                return int(s)

            if code == 127:  # backspace
                s = s[:-1]

    return curses.wrapper(_get_number)

print(get_number(10))