4

I made a super rudimentary stopwatch in python, just to get myself more acclimated with it, (It's my first programming language)and I've been trying to get the code to stop running when a key is pressed (using keyboard interrupt) but the code basically ignores keyboard interrupt and keeps going on forever. (here's my code for reference)

# Time
import time
import sys
timeLoop = True
# Variables to keep track and display
Sec = 0
Min = 0
Hour = 0
# Begin Process
timeloop = True
while timeloop == True:
    try:
        Sec += 1
        print(str(Hour) + " Hrs " + str(Min) + " Mins " + str(Sec) + " Sec ")
        time.sleep(1)
        if Sec == 60:
            Sec = 0
            Min += 1
            print(str(Min) + " Minute")
            if Min == 60:       
                Sec = 0
                Min = 0 
                Hour += 1
                print(str(Hour) + " Hours")
    except KeyboardInterrupt:
        sys.exit(0)
BenT
  • 3,172
  • 3
  • 18
  • 38
Deity3
  • 43
  • 3

2 Answers2

4

Use a second thread (https://en.wikipedia.org/wiki/Multithreading_(computer_architecture), How to use threading in Python?):

def quit_on_user_input():
    input = raw_input("Press any key to quit.")
    # thread will lock up and wait for user to input. That's why this is on a separate thread.
    sys.exit(0)

quit_thread = threading.Thread(target=quit_on_user_input, args=[])
quit_trhead.start()
# The rest of your code. quit_thread will run in the background and therefor won't lock up your main thread.
Ian Kirkpatrick
  • 1,861
  • 14
  • 33
2

The KeyboardInterrupt exception is thrown when the user quit's the program with ctrl + c. You will need to use another method to detect a key press. This answer seems to have a good cross-platform class to check stdin.

EDIT: The answer I linked above would require the user to press enter, so that could work if you run it in a different thread.

The following method should work on any keypress but only on Windows.

import msvcrt
# Time
import time
import sys
timeLoop = True
# Variables to keep track and display
Sec = 0
Min = 0
Hour = 0
# Begin Process
while True:
    try:
        Sec += 1
        print(str(Hour) + " Hrs " + str(Min) + " Mins " + str(Sec) + " Sec ")
        time.sleep(1)
        if Sec == 60:
            Sec = 0
            Min += 1
            print(str(Min) + " Minute")
            if Min == 60:
                Sec = 0
                Min = 0
                Hour += 1
                print(str(Hour) + " Hours")
        if msvcrt.kbhit():
            break
    except KeyboardInterrupt:
        break

EDIT2: Found a library for kbhit that has cross-platform support. In the example below I have saved it in the same directory as kbhit.py and have imported it at line #1.

from kbhit import KBHit
# Time
import time
import sys
timeLoop = True
# Variables to keep track and display
Sec = 0
Min = 0
Hour = 0

k = KBHit()
# Begin Process
while True:
    try:
        Sec += 1
        print(str(Hour) + " Hrs " + str(Min) + " Mins " + str(Sec) + " Sec ")
        time.sleep(1)
        if Sec == 60:
            Sec = 0
            Min += 1
            print(str(Min) + " Minute")
            if Min == 60:
                Sec = 0
                Min = 0
                Hour += 1
                print(str(Hour) + " Hours")
        if k.kbhit():
            break
    except KeyboardInterrupt:
        break
Jim Wright
  • 5,905
  • 1
  • 15
  • 34
  • 1
    The problem with this is that the time it takes for the kbhit to be evaluated will throw off the timer. The timer MUST be a completely separate thread or else it will not truely be a millisecond. Devpending on how fast the processor is, we have no idea how long it could take to process kbhit. Especially with a slower language like Python. – Ian Kirkpatrick Jul 26 '17 at 19:34