Preventing hang with a timeout? - python

I've made a bot that uses the Selenium Webdriver Module to navigate a website. Unfortunately I've noticed that the script will sometime stop when it tries to click a button. The code is simple. I try to click the button, if I can't we wait a second and try again. It works, but at seemingly random times (sometimes after 10 minutes, sometimes after several hours) it just stops after clicking the button.
while 1:
try:
#Try to click the button
confirmButton = driver.find_element_by_name("confirm")
confirmButton.click()
#If we can't, wait a second and try again
except:
time.sleep(1)
I've been thinking about creating some way to detect this, thus being able to timeout the current attempt to click, but I can't seem to figure out how. The script of single threaded and I can't use the simple datetime technique, as it would never run that check, since it's still waiting for the button to have finished being clicked on.
Edit: Someone asked me how I knew it was hanging and not just retrying indefinitely. I did a test where I printed a number for each line that was executed and when I the hang occurred it would not execute any of he lines below confirmButton.click(). I think that is proof that it's hanging and not retrying indefinitely. Or maybe not?

Your problem can be solved with a timeout: launch a function in a separate thread and stops after a certain time limit if the function is not finished.
Here is the example
from threading import Thread
from time import sleep
def threaded_function():
confirmButton = driver.find_element_by_name("confirm")
confirmButton.click()
if __name__ == "__main__":
thread = Thread(target = threaded_function)
thread.start()
thread.join(1)# this means the thread stops after 1 second, even if it is not finished yet
print ("thread finished...exiting")
Hope that helps, and tell me if it does not solve the prob.

Related

Stuck in a loop - Threaded continues while loop prevents code from moving forward (Python)

EDIT:
I apparantly wasn't aware of daemon threads.. This solved the main issue..
Now just puzzling to keep the loop checking for button press, whether it has been pressed or not =)
I'm trying to stop a raspberry pi running code when I press a button (emergency stop button connected to the pins).
So far it's not working out. (In my example code I use code to switch the light of the button to make testing easier).
The threading seems to be working well, however the shell program installed in the pi running the code, first 'test runs' the code to check for errors before actually executing. In my while not read_button() code, the 'checking' of the code gets stuck on the 'while not' until I press the button; not ideal..
Reversing the code and having while read_button() or only if read_button() doesn't actually respond to my button press, since likely the code finishes after checking instead of continuously check.
So.. How to solve this? A continues loop stops my code from proceeding until the while loop is broken (I did join the thread in the end..). A non-continues loop doesn't function, since it won't continuously check for the button press..
To make things worse; after the emergency stop was performed I want the thread to still continue checking for button press after (the user might decide to resume the program and have to hit emergency stop again later on the way within the same code).
I feel like I'm in an endless loop myself trying to fix this =P
(Sorry for the lengthy post and sorry for any noob-terms used, I'm very new to this; only picked programming up 3 weeks ago)
Thank you very much in advance!!
def button_check():
while not read_button(): #developer API
if read_button():
set_button_light(blue=True) #developer API
t = Thread(target=button_check)
t.start()
time.sleep(20) #just to give me time to test
t.join()

How to run tasks periodically without interrupting the whole program

I have a program that constantly runs if it receives an input, it'll do a task then go right back to awaiting input. I'm attempting to add a feature that will ping a gaming server every 5 minutes, and if the results every change, it will notify me. Problem is, if I attempt to implement this, the program halts at this function and won't go on to the part where I can then input. I believe I need multithreading/multiprocessing, but I have no experience with that, and after almost 2 hours of researching and wrestling with it, I haven't been able to figure it out.
I have tried to use the recursive program I found here but haven't been able to adapt it properly, but I feel this is where I was closest. I believe I can run this as two separate scripts, but then I have to pipe the data around and it would become messier. It would be best for the rest of the program to keep everything on one script.
'''python
def regular_ping(IP):
last_status = None
while True:
present_status = ping_status(IP) #ping_status(IP) being another
#program that will return info I
#need
if present_status != last_status:
notify_output(present_status) #notify_output(msg) being a
#program that will notify me of
# a change
last_status = present_status
time.sleep(300)
'''
I would like this bit of code to run on its own, notifying me of a change (if there is one) every 5 minutes, while the rest of my program also runs and accepts inputs. Instead, the program stops at this function and won't run past it. Any help would be much appreciated, thanks!
You can use a thread or a process for this. But since this is not a CPU bound operation, overhead of dedicating a process is not worth it. So a thread would be enough. You can implement it as follows:
import threading
thread = threading.Thread(target=regular_ping, args=(ip,))
thread.start()
# Rest of the program
thread.join()

Getting stuck executing infinite javascript loop in Python's Selenium chromedriver

I am trying to build a service where users can insert their Javascript code and it gets executed on a website of their choice. I use webdriver from python's selenium lib and chromedriver. The problem is that the python script gets stuck if user submits Javascript code with infinite loop.
The python script needs to process many tasks like: go to a website and execute some Javascript code. So, I can't afford to let it get stuck. Infinite loop in Javascript is known to cause a browser to freeze. But isn't there some way to set a timeout for webdriver's execute_script method? I would like to get back to python after a timeout and continue to run code after the execute_script command. Is this possible?
from selenium import webdriver
chromedriver = "C:\chromedriver\chromedriver.exe"
driver = webdriver.Chrome(chromedriver)
driver.get("http://www.bulletproofpasswords.org/") # Or any other website
driver.execute_script("while (1); // Javascript infinite loop causing freeze")
You could set a timeout for your driver.execute_script("while (1);") call.
I have found another post that could solve this issue.
Basically, if you are on a Unix system, you could use signal to set a timeout for your driver.execute_script("while (1); call.
Or if you could run it in a separate process and then end the process if it takes too long using multiprocessing.Process. I'm including the example that was given in the other post:
import multiprocessing
import time
# bar
def bar():
for i in range(100):
print "Tick"
time.sleep(1)
if __name__ == '__main__':
# Start bar as a process
p = multiprocessing.Process(target=bar)
p.start()
# Wait for 10 seconds or until process finishes
p.join(10)
# If thread is still active
if p.is_alive():
print "running... let's kill it..."
# Terminate
p.terminate()
p.join()

Why is KeyboardInterrupt not working for Python pyautogui script? Alternative way to exit program/loop?

I am trying to complete a simple GUI automation program that merely opens a web page and then clicks on a specific spot on the page every 0.2 seconds until I tell it to stop. I want my code to run and have its loop run infinitely until a keybind I specify breaks the loop (or entire program). I started out with the classic KeyboardInterrupt, which supposedly enables CTRL+C to exit a program. Here is my code:
import webbrowser, pyautogui, time
webbrowser.open('https://example.com/')
print('Press Ctrl-C to quit.')
time.sleep(5)
#pyautogui.moveTo(1061, 881)
try:
while True:
time.sleep(0.2)
pyautogui.click(1061,881)
except KeyboardInterrupt:
print('\nDone.')
Unfortunately, KeyboardInterrupt and using CTRL-C to exit do not seem to work for this script (likely due to the while loop?). This causes the loop to continue to run infinitely without a way to be stopped. So my questions are: why isn't the Keyboard Interrupt working? I've seen similar examples in other scripts. Additionally, if the KeyboardInterrupt doesn't work, is there a way I can code a simple keybind to exit the program/loop?
Use the following code
pyautogui.FAILSAFE = True
Then to stop, move the mouse to the upper-left corner of the screen
I suspect it may have something do to with you having a different active window than the script; when you use webbrowser, open a webpage, and click on it, it moves your active window to the webpage rather than the Python console. So ctrl+c will only produce a KeyboardInterrupt when the console is your active window. Your script may be in fact correct; but your active window is not on Python, so you would have to test it by clicking back into the Python console while the program runs.
To answer your comment: No, I do not know of any other "quick" way to do such a thing.
I'm late, but I can provide a solution which allows you to press CTRL + C to stop the program. You need to install the keyboard module and use keyboard.is_pressed() to catch when you press the keys you want as flag:
import keyboard
# You program...
while True:
time.sleep(0.2)
pyautogui.click(1061,881)
if keyboard.is_pressed("ctrl+c"):
break
You need to be careful though because the program will check if you have pressed the keys only when it executes the if statement. If your program runs for 10 seconds and you place the if at the end, you will only be able to exit every 10 seconds and for a very brief moment.
I also suggest to keep the keys pressed while you wait for the program to catch them to avoid missing the moment.
If you instead need to instantly terminate the program without having to always check if CTRL+C are pressed, you can place it in a process and kill it whenever you want. It's a bit overkill and it's not the recommended way, but if you really need it, here it is.
import pyautogui
import keyboard
import time
from multiprocessing import Process
def execute_program():
"""Long program which you want to interrupt instantly"""
while True:
pyautogui.click()
time.sleep(10)
if __name__ == '__main__':
# The failsafe allows you to move the cursor on the upper left corner of the screen to terminate the program.
# It is STRONGLY RECOMMENDED to keep it True
pyautogui.FAILSAFE = True
# Spawn and start the process
execute_program_process = Process(target=execute_program)
execute_program_process.start()
while True:
if keyboard.is_pressed('ctrl+c'):
execute_program_process.terminate()
break
print('\nDone.')

Waiting for some time before executing the next segment of codes in python3.2

I am writing a code to run a gui application(winmerge) and then send some keystrokes to it. I need to wait for some time within the program till the GUI finishes running and then send some keystrokes to it to save the report. How do I implement this? wait() isn't working as after invoking it I can't send keys to the same window.
from time import sleep
print "hi,"
sleep(5)
print "this is printed 5 seconds later"

Categories