user3211857
user3211857

Reputation: 117

Python timer for timing

This program asks the user questions, but only gives him/her 10 seconds to answer each one. If they answer the question within the time limit, the program move on to the next question at that instant. Also, if they don't answer within the time limit, the program will skip onto the next question after 10 seconds. I know about the timer class, how can I integrate it to do this? Here is my code I have so far. Don't worry about the pmXXXXX stuff, it's a software I'm using for school project.

    #question1
one = raw_input("Question 1:" + "\n" + qa + "\n" + "x" + "\n" + "A. Brightens it" + "\n" + "B. A gradient of black to white." + "\n" + "C. A color pallete.")
if(one.lower() == "b"):
    print "Congrats! 10 points."
        pmNewComputedImage("Question 1 Answer", 256, 256, "x")
        score += 10
else:
        print "Wrong. -10 points. Here's the answer."
        window1 = pmNewComputedImage("Question 1 Answer", 256, 256, "x")
        score -= 10



#question2
pmNewComputedImage("Question 2", 256, 256, "x*2")
two = raw_input("Question 2:" + "\n" + qb + "\n" + "A. x/2" + "\n" + "B. y/2" + "\n" + "C. x*2")
if (two.lower() == "c"):
    print "Congrats! 10 points."
    score += 10
else:
    print "Wrong -10 points. The answer is C."
    score -= 10


def stopwatch(seconds):
    import time
    start = time.time()
    time.clock()
    elapsed = 0
    while elapsed < seconds:
                elapsed = time.time() - start
                print "Seconds count: %02d" % elapsed
                time.sleep(1)

Upvotes: 0

Views: 202

Answers (1)

abarnert
abarnert

Reputation: 365717

The raw_input function just isn't going to return until the user types something, so you can't directly do this.

There are multiple ways around it. You can run the timer in a background thread and use signals to interrupt the main thread; you can just use signal.alarm to do it automatically without even needing a background thread (but not on Windows); you can put sys.stdin in nonblocking mode and use lower-level I/O to read instead of raw_input; you can do the input in a child process and terminate it if it takes too long, etc.

Here's an example of the first version which may even work on Windows, although I won't promise that it will in practice:

import os
import signal
import threading

try:
    mysig = signal.CTRL_C_EVENT
except NameError:
    mysig = signal.SIGINT

def timed_raw_input(prompt, timeout):
    t = threading.Timer(timeout, lambda: os.kill(os.getpid(), mysig))
    try:
        t.start()
        result = raw_input(prompt)
    except KeyboardInterrupt:
        return '' # or whatever you want to do on timeout
    else:
        t.cancel()
        return result

I'm not sure if CTRL_C_EVENT really does raise KeyboardInterrupt on Windows; you may have to install your own handler with signal.signal. Read the linked docs, and test it yourself and see. If you have to install a signal handler, you might as well use one of the other available cross-platform signals instead of CTRL_C_EVENT, and raise your own custom exception instead of KeyboardInterrupt.

Upvotes: 1

Related Questions