I have a program that takes a very long time to run, and I want it to be able to do what it needs to do but then if the user hits a specific key then I want the loop to break at a certain point. Most Q&A's I have seen pertaining to this problem prompt the user to enter something on each iteration of the loop, however I do not want this. I want the loop to run undisturbed until it needs to quit.
The script will be running as an executable in a command prompt (Windows) so I guess the user could just close the window but I want the loop to break at a certain point. For example:
while True:
print "Doing whatever I feel like"
userinput = raw_input()
if userinput == 'q':
break
So this keeps printing until the user enters 'q', but it prompts the user for input each iteration. How can I avoid this?
If you do not need to stop at a specific point, but just to be able to stop it, you could use a try/except with KeyboardInterrupt (Ctrl-C).
try:
while True:
print "Doing whatever I feel like"
except KeyboardInterrupt:
exit
When the user hits CTRL-C it will exit.
Or this:
import msvcrt
while True:
print "Doing whatever I feel like"
if msvcrt.kbhit(): # True if a keypress is waiting to be read.
if msvcrt.getch()=="q": # will not wait for Enter to be pressed
break
Check msvcrt.
Two possible solutions:
1. Press Ctrl-C to close your program. This also works on linux.
2.
while True:
for _ in range(100)
print "Doing whatever I feel like"
userinput = raw_input()
if userinput == 'q':
break
This only asks the user every 100 iterations.
Start a separate Thread to perform the computation that you need to perform while self.flag == False, and the main program can just sit there waiting for the user input. Once the user input is given, set Thread.flag = True, which will stop the Thread. Wait for the Thread to finish and join, then you can exit from the main program as well.
Related
How would I go about looping these two actions only in the code.
driver.find_element_by_xpath("//*[#id='skipAnimation']").click() time.sleep(1) driver.find_element_by_xpath("// *[#id='openAnother']").click()
I don't want to loop the whole code I want these two codes to repeat until I stop it
Your goal is not really clear: "I don't want to loop the whole code I want these two codes to repeat until I stop it".
Do you expect to end the loop 'manually'?
If so, then you can ask for user input in Python with input().
If my understanding of the problem is correct, you want to run your two functions until you decide to manually stop them running?
I believe a while loop could be used for this task.
You have different options depending if you want to press a key at each iteration, or if you want it to loop until you press a specific key.
Press at each iteration:
while True: # infinite loop
user_input = input("Want to continue? ")
if user_input == "No":
break # stops the loop
else:
# do whatever computations you need
driver.find_element_by_xpath("//*[#id='skipAnimation']").click()
time.sleep(1)
driver.find_element_by_xpath("// *[#id='openAnother']").click()
print('looping')
Now, if you want it to constantly run, until you press a key, there are two options:
while True:
try:
# do whatever computations you need
driver.find_element_by_xpath("//*[#id='skipAnimation']").click()
time.sleep(1)
driver.find_element_by_xpath("// *[#id='openAnother']").click()
print('looping')
except KeyboardInterrupt:
break
Or
import msvcrt
while True:
# do whatever computations you need
driver.find_element_by_xpath("//*[#id='skipAnimation']").click()
time.sleep(1)
driver.find_element_by_xpath("// *[#id='openAnother']").click()
print('looping')
if msvcrt.kbhit():
break
But pay attention to the behavior if you're in a notebook.
I've been having a really hard time putting this problem into words. What I'm trying to do is to have a while-loop constantly running, unless I give a 'stop' command.
I'm making a fishing mini-game in a bigger game, and I want to be able to start fishing on command (which I have been able to do), and for the fishing to continue happening, until I eventually type 'stop'.
The way I've been doing things is that I ask for a command input, then do something based on the command. However, in this situation, I dont want to do that, because asking for the input pauses the while-loop.
I'm open to other suggestions on how to exit the while-loop with a certain command, but the game is text-based, so ideally I want a text command to exit.
if command == 'fish':
print('You start fishing')
while True:
# fishing happens, you may or may not catch something
# if you enter a command ('exit'), you stop fishing
# I dont, however, want the code to pause to ask for a command.
# I want it to be uninterrupted fishing, until I choose to exit
you need 2 loops here and flags , when user pauses the pauseFlag become True and your code will come out from the inner loop and when he unpause the pauseFlag switches to False and Code will enter the inner loop again and the game will resuming.
Somthing like below:
while(quitFlag):
while(!pauseFlag):
#your code
if(somthing):
pauseFlag = True
if(somthing):
pauseFlag = False # and it make the code goes to the second loop again and resume the game
Maybe you wonder : what is quitFlag ? as you see it's the condition of the first loop. Whenever quitFlag switches to false the game will shut down and The user can't resume the game and he must start the game all over.
I have a function that has a continual loop asking the user for their input using python's builtin input(prompt). I also have a separate thread doing some work, and when a certain condition is met in that thread, the input prompt should change.
So, say at startup the prompt is "Input: " but then in the middle of the thread's work, a condition is met, so the prompt should be switched to "Go Ahead, Type: ". Now if the user doesn't enter anything at that first prompt, but the thread reaches the point where the prompt is switched, then we are still stuck on that first blocking input call that has "Input: " as it's prompt.
# Start the thread that does some work and eventually changes the prompt
myThread.start()
#Start looping to ask for user input, get the prompt from the thread
while True:
userInput = input(myThread.get_prompt())
<do something with input>
I know I can accomplish this with select([stdin],[],[],0.0) to poll stdin before doing a stdin.readline() and then just print the prompt again if 1) we got user input or 2) if the prompt changed.
However, I'd like to find a solution that uses Python's builtin input() function so that I can set tab completion with python's readline module.
I tried playing around with a signal that would basically interrupt input() every couple seconds. With this I would need to make it appear seamless that a new input() call was made without it reprinting the prompt. So something like:
myThread.start()
while True:
userInput = None
signal(SIGALRM, handler)
signal.alarm(3)
try:
userInput = input("\r" + myThread.get_prompt())
except TimeoutError:
pass
finally:
signal.alarm(0)
<do something with input>
def handler(signum, frame):
raise TimeoutError
Which is messy, but then when it times out, and the new input() is called, the current line buffer gets printed but the cursor is at the front of it. So if I type "aaa" then it reprints the "aaa" but the cursor is not at the end of that buffer, it is at the beginning.
Any suggestions?
Update: I can certainly try to play around more with the signal option. It seems like that might be my best option so far. I just can't seem to get the cursor to move to the end of the input buffer if the user has already started typing something. I don't want the user to be aware of the call timing out and being called again.
Ok I figured it out. And it's way better than using the signal alarm to timeout.
In case anyone in the future stumbles across this specific problem, here is essentially what I did:
import threading
import time
import readline
import sys
class MyThread(threading.Thread):
def __init__(self):
super(MyThread, self).__init__()
# Set the initial prompt
self.prompt = "Input: "
def run(self):
time.sleep(6)
# Now we want to change the prompt so that next time input loop asks for prompt it is correct
self.set_prompt("Go ahead, type: ")
# Now overwrite what was there in the prompt
sys.stdout.write("\r" + self.get_prompt())
sys.stdout.flush()
# Get the current line buffer and reprint it, in case some input had started to be entered when the prompt was switched
sys.stdout.write(readline.get_line_buffer())
sys.stdout.flush()
def get_prompt(self):
return self.prompt
def set_prompt(self, new_prompt):
self.prompt = new_prompt
# Create and start thread
myThread = MyThread()
myThread.start()
# Input loop
while True:
userInput = input(myThread.get_prompt())
print("Got: " + userInput)
If you are using tab complete (which I didn't show here), you may notice that if you try to tab complete after the first time that the prompt switches (without accepting any input from the first prompt), then tab complete still thinks we are reading from the first prompt and will reprint that prompt. In that case, you will need to do the following:
readline.set_completion_display_matches_hook(display)
Where display is a function that does something like what our thread had to do to rewrite the correct prompt:
def display(substitution, matches, longest_match_length):
# Print the matches
print('')
buffer = ''
for match in matches:
buffer += match + " "
print(buffer)
# Rewrite the NEW prompt
sys.stdout.write(<prompt>)
sys.stdout.flush()
sys.stdout.write(readline.get_line_buffer())
sys.stdout.flush()
I'm new to programming so sorry in advance if this code is a bit messy.
I'm trying to write a program that would prompt the user to type "y" in the command prompt every 5 minutes (the user has 15 seconds to do so), and if the user does not, a browser window would open and play a video in order to wake them up. (link in the code bellow is only an example and not the actual loud sound used to wake the user up)
Currently, the question is only asked once, and then the program closes after 15 seconds have passed.
I've tried to look for what I'm doing wrong online, but I've not been able to understand my mistake.
anstoboot = input("Welcome to this short program that will try to make you stay awake! Type start and press enter to start the program")
if(anstoboot == "start" or anstoboot == " start" or anstoboot == "Start" or anstoboot == " Start"):
persontypedno = False
while not persontypedno:
try:
persontypednoans = input("Are you awake? (Type y an press enter)")
time.sleep(15)
if(persontypednoans == "y" or persontypednoans == " y"):
time.sleep(15)
persontypedno = True
except:
print("You fell asleep. Please reopen the program")
webbrowser.open ("https://www.youtube.com/watch?v=ZcoqR9Bwx1Y", new=1, autoraise=True)
Any help is appreciated.
I would recommend using an endless loop which you break if a certain condition is met, after breaking anything outside the loop will be executed, so put your browser launching thing there, if you want the program to keep going after the browser has been opened, enclose everything in another endless loop.
# First endless loop to keep restarting everthing
while True:
# Loop that keeps on going if the user enters something into the input
while True:
# Sleep for 5 mins
time.sleep(300)
rsp = input("Type something if you are not sleeping yet: ")
time.sleep(15)
# Break the current loop if the person hasn't wrote anything
if len(rsp) <= 0:
break
*** code for launching the browser ***
I currently have a program that runs at regular intervals. Right now the program runs continuously, checking for new files every 30 minutes:
def filechecker():
#check for new files in a directory and do stuff
while True:
filechecker()
print '{} : Sleeping...press Ctrl+C to stop.'.format(time.ctime())
time.sleep(1800)
However, I'd also like the user to be able to come to the terminal and enter a keystroke to manually call filechecker() instead of either waiting for the program from waking from sleep or having to relaunch the program. Is this possible to do? I tried to look at using threading, but I couldn't really figure out how to wake the computer from sleep (don't have much experience with threading).
I know I could just as easily do :
while True:
filechecker()
raw_input('Press any key to continue')
for full manual control, but I want my to have my cake and eat it too.
You can use a try/except block with KeyboardInterrupt (which is what you get with Ctrl-C while in the time.sleep(). Then in the except, ask the user if they want to quit or run filechecker immediately.
Like:
while True:
filechecker()
try:
print '{0} : Sleeping...press Ctrl+C to stop.'.format(time.ctime())
time.sleep(10)
except KeyboardInterrupt:
input = raw_input('Got keyboard interrupt, to exit press Q, to run, press anything else\n')
if input.lower() == 'q':
break
The solution provided by clindseysmith introduces one more key press than what the original question was asking for (at least, my interpretation thereof). If you really want to combine the effect of the two snippets of code in the question, i.e., you don't want to have to press Ctrl+C for calling the file checker immediately, here's what you can do:
import time, threading
def filechecker():
#check for new files in a directory and do stuff
print "{} : called!".format(time.ctime())
INTERVAL = 5 or 1800
t = None
def schedule():
filechecker()
global t
t = threading.Timer(INTERVAL, schedule)
t.start()
try:
while True:
schedule()
print '{} : Sleeping... Press Ctrl+C or Enter!'.format(time.ctime())
i = raw_input()
t.cancel()
except KeyboardInterrupt:
print '{} : Stopped.'.format(time.ctime())
if t: t.cancel()
The variable t holds the id of the thread that is scheduled next to call the file checker. Pressing Enter cancels t and reschedules. Pressing Ctrl-C cancels t and stops.
You could make it so that by pressing ctrl+c filechecker() would run by using this:
def filechecker():
#check for new files in a directory and do stuff
filechecker()
while True:
print '{} : Sleeping...press Ctrl+C to run manually.'.format(time.ctime())
try:
time.sleep(1800)
except KeyboardInterrupt:
filechecker()
filechecker()