On Windows you can use the msvcrt module's kbhit and getch functions (I modernized this code example a little bit):
import sys
import time
import msvcrt
def read_input(caption, timeout=5):
    start_time = time.time()
    print(caption)
    inpt = ''
    while True:
        if msvcrt.kbhit():  # Check if a key press is waiting.
            # Check which key was pressed and turn it into a unicode string.
            char = msvcrt.getche().decode(encoding='utf-8')
            # If enter was pressed, return the inpt.
            if char in ('\n', '\r'): # enter key
                return inpt
            # If another key was pressed, concatenate with previous chars.
            elif char >= ' ': # Keys greater or equal to space key.
                inpt += char
        # If time is up, return the inpt.
        if time.time()-start_time > timeout:
            print('\nTime is up.')
            return inpt
# and some examples of usage
ans = read_input('Please type a name', timeout=4)
print('The name is {}'.format(ans))
ans = read_input('Please enter a number', timeout=3)
print('The number is {}'.format(ans))
I'm not sure what exactly you have to do on other operating systems (research termios, tty, select).
Another possibility would be the curses module which has a getch function as well and you can set it to nodelay(1) (non-blocking), but for Windows you first have to download curses from Christopher Gohlke's website. 
import time
import curses
def main(stdscr):
    curses.noecho()  # Now curses doesn't display the pressed key anymore.
    stdscr.nodelay(1)  # Makes the `getch` method non-blocking.
    stdscr.scrollok(True)  # When bottom of screen is reached scroll the window.
    # We use `addstr` instead of `print`.
    stdscr.addstr('Press "q" to exit...\n')
    # Tuples of question and answer.
    question_list = [('4 + 5 = ', '9'), ('7 - 4 = ', '3')]
    question_index = 0
    # Unpack the first question-answer tuple.
    question, correct_answer = question_list[question_index]
    stdscr.addstr(question)  # Display the question.
    answer = ''  # Here we store the current answer of the user.
    # A set of numbers to check if the user has entered a number.
    # We have to convert the number strings to ordinals, because
    # that's what `getch` returns.
    numbers = {ord(str(n)) for n in range(10)}
    start_time = time.time()  # Start the timer.
    while True:
        timer = time.time() - start_time
        inpt = stdscr.getch()  # Here we get the pressed key.
        if inpt == ord('q'):  # 'q' quits the game.
            break
        if inpt in numbers:
            answer += chr(inpt)
            stdscr.addstr(chr(inpt), curses.A_BOLD)
        if inpt in (ord('\n'), ord('\r')):  # Enter pressed.
            if answer == correct_answer:
                stdscr.addstr('\nCorrect\n', curses.A_BOLD)
            else:
                stdscr.addstr('\nWrong\n', curses.A_BOLD)
        if timer > 3:
            stdscr.addstr('\nToo late. Next question.\n')
        if timer > 3 or inpt in (ord('\n'), ord('\r')):
            # Time is up or enter was pressed; reset and show next question.
            answer = ''
            start_time = time.time()  # Reset the timer.
            question_index += 1
            # Keep question index in the correct range.
            question_index %= len(question_list)
            question, correct_answer = question_list[question_index]
            stdscr.addstr(question)
# We use wrapper to start the program.
# It handles exceptions and resets the terminal after the game.
curses.wrapper(main)