AutoKey repeating loop - python

I have been searching forums and the web for hours looking into a way of making a repeating python loop for Autokey. The goal is to allow timed intervals of key presses, such as pressing "1" every 16 seconds, "2" every 30, so on and so forth for as many keys as I may need (likely less than 8). I would also want to be able to end this process at the click of any combination. I have been testing looping only 1 keyboard input every 5 seconds, and I can easily make that work. I am fairly new to python and coding in general, and what has worked for me in the past does not here. I've tried:
import time
import sys
try:
while True:
time.sleep(5)
keyboard.send_key("4")
except KeyboardInterrupt:
exit(0)
sys.exit(0)
and variations there of, such as switching the while loop and try/except. It feels as though my keyboardinterrupt is not working properly, I've used ctrl -c and ctrl break, to no avail. Any help is appreciated. Thank you in advance.

I have a similar requirement, and from my searching, I found a comment from AutoKey developer.
These codes could be what you need:
while True:
retCode = keyboard.wait_for_keypress(
'c', modifiers=['<ctrl>'], timeOut=5)
if retCode:
break
keyboard.send_key("4")

KeyboardInterrupt only catches Ctrl+C if it was send to the controlling terminal. This means that if you're pressing Ctrl+C from a different window, it will not catch.
To work around this, you need to register a keyboard shortcut on Ctrl+C, and have it send a signal to your main script.

Related

How to make python script more efficient while loop

I have a simple python script that listens to my keypress and executes a command upon keypress. In my code, I have an infinite while loop which is pretty harsh on the performance of my computer. I'm wondering what's a better way to achieve the same behavior with less impact on the performance. The objective is to print a text which says
You Pressed A Key!
Every time I press a certain key, in this case, 'h', I want to be able to press h multiple times not just once hence the while loop.
import keyboard
while True:
if keyboard.is_pressed('h'):
print('You Pressed A Key!')
You may want to make the process sleep for a while using:
import time
time.sleep(number_of_seconds)

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.')

How to hard suspend or pause a python script after it runs so it doesn’t force close upon completion?

Hi so I’m working on a python script that involves a loop function, so far the loop function process is failing for some reason(although I kinda know why) but the problem I’ve got os.system(‘pause’) and also input(“prompt:”) at end of the code in order to pause all activity so I can read the error messages prior to script completion and termination but the script still shuts down, I need a way to HARD pause it or freeze before the window closes abruptly. Need help and any further insight.
Ps. Let me know if you need any more info to better describe this problem.
I assume you are just 'double clicking' the icon on Window Explorer. This has the disadvantage which you are encountering here in that the shell (terminal window) closes when the process finishes so you can't tell what went wrong if it terminated due to an error.
A better method would be to use the command prompt. If you are not familiar with this, there are many tutorials online.
The reason this will help with your problem is that, once navigating to the script's containing directory, you can use python your_script.py (assuming python is in your path environmental variable) to run the script within the same window.
Then, even if it fails, you can read the error messages as you will only be returned to the command line.
An alternative hacky method would be to create a script called something like run_pythons.py which will use the subprocess module to call your actual script in the same window, and then (no matter how it terminates), wait for your input before terminating itself so that you can read the error messages.
So something like:
import subprocess
subprocess.call(('python', input('enter script name: ')))
input('press ENTER to kill me')
I needed something like this at one point. I had a wrapper that loaded a bunch of modules and data and then waited for a prompt to run something. If I had a stupid mistake in a module, it would quit, and that time that it spent loading all that data into memory would be wasted, which was >1min. For me, I wanted a way to keep that data in memory even if I had an error in a module so that I could edit the module and rerun the script.
To do this:
while True:
update = raw_input("Paused. Enter = start, 'your input' = update params, C-C = exit")
if update:
update = update.split()
#unrelevant stuff used to parse my update
#custom thing to reload all my modules
fullReload()
try:
#my main script that needed all those modules and data loaded
model_starter.main(stuff, stuff2)
except Exception as e:
print(e)
traceback.print_exc()
continue
except KeyboardInterrupt:
print("I think you hit C-C. Do it again to exit.")
continue
except:
print("OSERROR? sys.exit()? who knows. C-C to exit.")
continue
This kept all the data loaded that I grabbed from before my while loop started, and prevented exiting on errors. It also meant that I could still ctrl+c to quit, I just had to do it from this wrapper instead of once it got to the main script.
Is this somewhat what you're looking for?
The answer is basically, you have to catch all your exceptions and have a method to restart your loop once you figured out and fixed the issue.

What is the best way to pause/stop/command a Python script anytime anywhere?

I have a Python script running selenium framework in a command line and running continuously to control Chrome do background data processing and monitoring. My simplified code structure is as following
while True:
Do_task1() # a blocking function
Do_task2() # another blocking fucntion
... # calling many blocking functions below, including wait(), time.sleep()
I need a way to interrupt the script anytime and anywhere to pause, terminate safely and give commands. What are the best ways to do this?
I've thought and tried of several ways but I am not exactly sure how to approach it:
I tried this:
if msvcrt.kbhit():
key = msvcrt.getch().decode("utf-8").lower()
if key == "j":
self.setting1 = True
elif key == "k":
self.setting2 = True
in the while loop, but it has to pass through bunch of blocking calls before reacting to my keypresses. And the command isn't exactly accepting my keyboard input in real time, that is I'll enter a character input, and I think it will be in the background buffer, then once the code execution reaches the code above, it starts to do stuff.
For terminating the script, I just do Ctrl-C in the CMD window, which I don't think it's the best way, and I should properly end the program ending background processes like Chromedriver.
I thought of having a GUI which runs somehow asynchronously and I can have buttons for pausing, and terminating the script. But I am not exactly sure how to approach it, or if this is a good idea to even try. Any suggestion is welcomed.
Use a script monitoring/workflow monitoring framework like AirBnB's Airflow or Luigi. I had only done brief research on this.
A related question but I don't need to return exactly where it's left off
I usually use try and except to do this
while True:
try:
Do_Task1()
Do_Task2()
except KeyBoardInterrrupt:
break

pyHook stops receiving Key press events (randomly)?

I have a program that captures all key presses using pyHook, then runs a few functions.
I notice that after a while (of random duration), the program was stop receiving key triggers, even though I am pressing keys?
Is pyHook unstable?
I'm not changing what keys are pressed or pressing them prematurely or anything like that.
Here's my code:
import time
import win32api
import win32con
import pythoncom
import pyHook
import os
import ctypes
def Click(x,y):
win32api.SetCursorPos((x,y))
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,x,y,0,0)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,x,y,0,0)
def DeleteRun(event):
if event.Ascii == 96:
BreakHook()
return False
Click(1250, 741)
time.sleep(0.2)
Click(649,261)
time.sleep(0.2)
Click(651, 348)
time.sleep(0.2)
Click(800, 442)
time.sleep(0.2)
Click(865, 612)
time.sleep(0.2)
Click(25, 744)
time.sleep(3)
Click(25, 744)
time.sleep(1.5)
Click(1112,297)
Click(145,392)
return True
def BreakHook():
ctypes.windll.user32.PostQuitMessage(0)
KeyGrabber = pyHook.HookManager()
KeyGrabber.KeyDown = DeleteRun
KeyGrabber.HookKeyboard()
pythoncom.PumpMessages()
Why does is suddenly stop working?
It's very frustrating as the process remains active on my computer, even if I stop the program through the IDE.
Specs:
python 2.7.2
Windows 7 (32)
Similar (dare I say identical?) problems were discussed and resolved here: pyHook + pythoncom stop working after too much keys pressed [Python]
and here: Pyhook stops capturing key events after 6 presses
You may be trying to do to much from withing the event callback.
Any event function callback as configured via HookManager and PumpMessages should return as quickly as possible.
When you press a key, Windows is kind enough to inform you of the event, but there may be other programs who also need the event. You are doing sleep calls within your event, but while you sleep, Windows is waiting for your response on THIS callback.
My guess is that after a certain number of opportunities to return in a timely manner, your event registration is being voided and ignored by Windows.
Move your sleep commands outside of the event, and instead trigger your actually click-sleep sequence outside of the hookmanager callback.
Edit: Links/Reference:
The PyHook API Documentation is one of the best (unfortunately), http://pyhook.sourceforge.net/doc_1.5.0/ If you notice the many things you can do from within the event, it becomes clear why time is of the essence. Windows wants to know how to handle the keypress (for example), and keypresses happen very fast, so it wants to know ASAP.
Its important to understand that PyHook is a very thin layer, and most of the functionality is provided by Windows, so the best documents are from MSDN http://msdn.microsoft.com/en-us/library/ms632589(v=vs.85).aspx. Also might want to take a look up a level at some of the information on 'Messages' (thats where our PumpMessages ultimately derives) The written text is very descriptive, and many of the constants and values are reflected properly through PyHook, although the good code segments are not written in Python.
Here is a pretty direct reference to proper handling of Messages (which is what hookmanager knows how to get, and by which PumpMessages delivers), http://msdn.microsoft.com/en-us/library/ms644927(v=vs.85).aspx
If a top-level window stops responding to messages for more than several seconds, the system considers the window to be not responding.
and
Message Handling
An application must remove and process messages posted to the message queues of its threads
When you call your sleeps, you are hanging in your current message, and neglecting the others that might be stacking up. Even if you grab the message and immediately return, Windows doesn't care what you do with it, as long as you are consuming.

Categories