I have an infinite while loop that I want to break out of when the user presses a key. Usually I use raw_input
to get the user\'s response; however, I need
Using the msvcrt
module as thebjorn recommended I was able to come up with something that works. The following is a basic example that will exit the loop if any key is pressed, not just enter.
import msvcrt, time
i = 0
while True:
i = i + 1
if msvcrt.kbhit():
break
time.sleep(0.1)
print i
I could not get some of the popular answers working. So I came up with another approach using the CTRL
+ C
to plug in user input and imbibe a keyboard interrupt. A simple solution can be using a try-catch block,
i = 0
try:
while True:
i+=1
print(i)
sleep(1)
except:
pass
# do what you want to do after it...
I got this idea from running a number of servers like flask and django. This might be slightly different from what the OP asked, but it might help someone else who wanted a similar thing.
On python 3.5 you can use the following code. It can be adjusted for a specific keystroke. The while loop will keep running until the user presses a key.
import time
import threading
# set global variable flag
flag = 1
def normal():
global flag
while flag==1:
print('normal stuff')
time.sleep(2)
if flag==False:
print('The while loop is now closing')
def get_input():
global flag
keystrk=input('Press a key \n')
# thread doesn't continue until key is pressed
print('You pressed: ', keystrk)
flag=False
print('flag is now:', flag)
n=threading.Thread(target=normal)
i=threading.Thread(target=get_input)
n.start()
i.start()
You can use non-blocking read from stdin:
import sys
import os
import fcntl
import time
fl = fcntl.fcntl(sys.stdin.fileno(), fcntl.F_GETFL)
fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, fl | os.O_NONBLOCK)
while True:
print("Waiting for user input")
try:
stdin = sys.stdin.read()
if "\n" in stdin or "\r" in stdin:
break
except IOError:
pass
time.sleep(1)
What you need is a non-blocking raw input, if you don't want to use threads there is a simple solution like this one below where he is doing a timeout of 20 ms and then raise and exception if the user doesn't press a key, if he does then the class returns the key pressed.
import signal
class AlarmException(Exception):
pass
def alarmHandler(signum, frame):
raise AlarmException
def nonBlockingRawInput(prompt='', timeout=20):
signal.signal(signal.SIGALRM, alarmHandler)
signal.alarm(timeout)
try:
text = raw_input(prompt)
signal.alarm(0)
return text
except AlarmException:
print '\nPrompt timeout. Continuing...'
signal.signal(signal.SIGALRM, signal.SIG_IGN)
return ''
Source code
I think you can do better with msvcrt:
import msvcrt, time
i = 0
while True:
i = i + 1
if msvcrt.kbhit():
if msvcrt.getwche() == '\r':
break
time.sleep(0.1)
print(i)
Sadly, still windows-specific.