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 raw_input
to not wait for the response. I want something like this:
print 'Press enter to continue.'
while True:
# Do stuff
#
# User pressed enter, break out of loop
This should be a simple, but I can't seem to figure it out. I'm leaning towards a solution using threading, but I would rather not have to do that. How can I accomplish this?
asked Dec 13, 2013 at 22:16
7
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]
answered Dec 13, 2013 at 22:43
1
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.
answered Dec 13, 2013 at 22:49
octrefoctref
6,3636 gold badges27 silver badges42 bronze badges
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[]
answered Nov 28, 2017 at 20:43
gtcodergtcoder
1412 silver badges6 bronze badges
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.
answered Feb 2, 2019 at 5:47
lu5erlu5er
2,9902 gold badges25 silver badges48 bronze badges
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
answered Dec 13, 2013 at 22:44
moisesvegamoisesvega
4251 gold badge5 silver badges16 bronze badges
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
answered Dec 13, 2013 at 22:32
I have defined the function which ask number input from the user and returns the factorial of that number. If user wants to stop they have to press 0 and then it will exit from the loop. We can specify any specific key to input 'n' to exit from the loop.
import math
def factorial_func[n]:
return math.factorial[n]
while True:
n = int[input["Please enter the number to find factorial: "]]
print[factorial_func[n]]
if n == 0:
exit[]
answered Jan 26, 2021 at 14:26