Python: A robust continuous loop with keyword keyboard interrupt - python

Currently I have a program which follows:
try:
while True:
print("Running")
except KeyboardInterrupt:
pass
The idea bring that the terminal will print "Running" until the user inputs CRTL+C, what I want to be able to do is have the program continue to run until a user enters a key word in additional to this. This is to make my program more robust so no accidental inputs could stop the loop.
Is there a way to do this?

Here a possible way to achieve that:
while True:
try:
print("Running")
except KeyboardInterrupt:
if input("Type exit to exit: ") != "exit":
continue
break
Or if you want to a more flexible escaping string you can declare it as follow:
escape_string = "exit"
while True:
try:
print("Running")
except KeyboardInterrupt:
if input(f"Type {escape_string} to exit: ") != escape_string:
continue
break

You need the try/except block to be inside the loop, so that the interrupt does not exit the loop. The exception handler activates the loop exit condition.
ans = ""
while ans != "please":
try:
print("Running")
sleep(1)
except KeyboardInterrupt:
ans = input("Please enter secret ")

Related

Every "q'" press print something in Python

Once I press "q" it prints this text many times. I want to print it once.
import keyboard
while True:
try:
if keyboard.is_pressed("q"):
print('q pressed')
except:
break
Your current code is constantly repeating check until q is pressed, which is not cpu efficient, and also once the q is pressed is_pressed will always be True - it does not automatically reset.
There is a good example of what you want in the docs. Do something like this:
keyboard.wait('q')
print('q pressed, continue...')
Note that this will block execution until q is pressed, and will continue after that. If you want to repeat process, simply put it inside while loop:
while True
keyboard.wait('q')
print('q pressed, waiting on it again...')
Hi you need to break in your try clause after printing in order for loop to end, just like you did in except;
while True:
try:
if keyboard.is_pressed("q"):
print('q pressed')
break
except:
break
The reason your code repeats is that you do not check for when q is released. this causes the condition if keyboard.is_pressed("q") to run multiple times
to stop this. you need to check for when q is released
for example
import keyboard
is_pressed = False
while True:
try:
if keyboard.is_pressed("q") && not is_pressed:
print('q pressed')
is_pressed = True:
if not keyboard.is_pressed("q"):
is_pressed = False
except:
break

How to break out of a loop nicely?

I have a program that does some work in a timed while loop like so:
import time
While True:
do something
time.sleep(60)
I would like to be able to break out of the loop nicely from the console and save some data on the way out. The solution I have thought of is to create a file when I want the program to quit and check for the file inside the loop like so.
from os.path import exists
While True:
do something
if exists('exit.txt'):
print('exiting')
clean_up()
time.sleep(60)
Is there a better way?
Put them into try catch statement. When you want to end the loop, exit the cycle through Ctrl+C, and then complete the work you want to finish:
>>> try:
... while True: pass
... except KeyboardInterrupt:
... print('hello')
...
[^C]
hello
Use the break keyword to exit a loop when a condition is met:
from os.path import exists
while True:
do_something()
if exists('exit.txt'):
print('exiting')
break
time.sleep(60)
clean_up()
As Mechanic Pig mentioned in his answer, if you want to be able to manually break out of it from the console, you could implement a KeyboardInterrupt handler:
while True:
try:
do_something()
if exists('exit.txt'):
print('exiting')
break
else:
time.sleep(60)
continue
except KeyboardInterrupt:
print('exiting')
break
clean_up()

is their a way to close the IDLE shell if they input something

is there a way on IDLE to close the users shell if they were to enter something that would be supposed to "quit"?
You can use exit(0) to terminate the program, as follows:
while True:
i = input()
if i == "quit":
exit(0)
else:
# do something
pass
For more information about what 0 for exit() means:
Difference between exit(0) and exit(1) in Python

When I enter no it doesn't execute properly

import webbrowser
import time
import sys
import urllib.request
def con():
cont = input("Do you want to continue? ")
if (cont.lower() == "yes" or cont.lower() == "y"):
main()
elif (cont.lower() == "no" or cont.lower() == "n"):
sys.exit()
else:
print("Invalid answer. Please try again")
time.sleep(1)
con()
def main():
try:
website = input("What website do you want to go to? (ex. Example.com) ")
fWebsite = "http://{}".format(website)
time.sleep(1)
if (urllib.request.urlopen(fWebsite).getcode() == 200):
webbrowser.open(fWebsite)
time.sleep(1)
except:
print("Invalid website. Please enter another one")
time.sleep(1)
main()
con()
main()
when the code runs con(), when ever I try to enter no, it always says invalid website. Please enter another one. How do I fix it to exit the program? everything else works it is just this one part.
The sys.exit function works by raising an SystemExit exception. Your code has a bare except block which is catching that exception and suppressing its normal purpose (that is, to exit quietly).
The best fix for this issue is to make your except clause more specific to the kinds of exceptions you expect to catch. It is almost always a bad idea to catch everything (the only exception to that is when you're catching all exceptions, but logging and re-raising most of them).
Since your specific code is trying to deal with exceptions from urllib, catching urllib.error.URLError is probably your best bet.

Python - Infinite while loop, break on user input

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?
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)
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.
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()
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.
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
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 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()

Categories

Resources