Comments (31)
Callbacks would be great. Doing a small application now where I have to import the keyboard-library as well in order to capture when the user presses a key combination and execute some Python-code.
from ahk.
Since we already have the python keyboard project for creating powerful hotkeys from scratch, maybe a useful goal for this project is to incorporate hotkey functionality in a way that makes it as easy as possible to port existing autohotkey hotkeys to this framework.
from ahk.
@maracko there are some improvements on the way that may help your use case. But let me try to answer your questions:
proper way to close the ahk executable on exit cause it sometimes is left active even after my python script stops?
This library uses finalizer hooks to ensure the AHK process (like those started for hotkeys) is closed. However, as mentioned in the official docs using os._exit
will not allow cleanup handlers to run. As such, the hotkey process may be left running.
So, in short, if your python script exits normally (even with an exception), there shouldn't be anything you need to do to ensure the ahk executable terminates.
There are, however, cases where cleanup might not run, such as when a Python fatal internal error is detected, or when os._exit()
is called.
In your example, changing os._exit(1)
to sys.exit(1)
should ensure the AHK process is closed.
there a way to start an event loop so the app doesn't close immediately after execution?
I'm 100% sure what you mean here.
For Hotkeys, the main Python script must continue to run for the hotkey to continue running. If your app consists only of the AHK hotkey, then you can do something like this:
ahk = AHK()
hotkey = ahk.hotkey("#n", "Run Notepad")
hotkey.start() # call .start() to start the AHK process listening to the hotkey
while True: # keep the main thread alive so hotkey will stay running
try:
time.sleep(0.5)
except KeyboardInterrupt:
hotkey.stop() # technically you don't have to call stop.
# The process will stop on its own when the script ends
break
There are a few improvements on the way that may help your situation:
-
as mentioned earlier Python callbacks for hotkeys are going to implemented in the near future. So something like
if ahk.key_state("Control") and ahk.key_state("Shift") and ahk.key_state("1")
could reasonably be re-written as a hotkey. -
There is a daemon feature coming in #111 that will offer greatly improved performance. Currently, each AHK command runs in its own process. The daemon feature will allow AHK commands to be executed in a single long-running AHK process, which should improve efficiency by an order of magnitude, especially for scripts that call methods in rapid succession.
Lastly, I may add a wait_forever
method to hotkeys... but it will likely just be something simple, like the while
loop I wrote above.
Hope that answers your question. Let me know if you still have other questions or always feel free to open another issue.
from ahk.
As an extended goal, something nice would be methods for remapping keys
from ahk.
Implemented with #10 is basic functionality for hotkeys that just setup a running script with the hotkey. Can only execute AHK code, no Python callbacks just yet, but I'd like to figure out if that is possible to do.
from ahk.
I have a pull request in for Callback functionality in the class Bindable_Hotkey
from ahk.
Does it support full autohotkey syntax for specifying the keystrokes that activate a hotkey as described here (including the modifier symbols, tilde, ampersand, UP, etc.):
https://www.autohotkey.com/docs/Hotkeys.htm
from ahk.
Yes
from ahk.
Another interesting project similar in spirit to this one is:
https://github.com/dc740/AutoHotPy
It also uses Python but leverages instead the more powerful lower-level Interception input driver
https://github.com/oblitum/Interception
to handle input from multiple devices and generate keystroke/mouse events for applications that aggressively try to prevent the use of hotkeys.
Wonder if there is a way to incorporate AutoHotPy (which has not seen any updates for a few years now) into the present framework so that the Interception driver can be used for hotkeys when necessary.
This project may be able to provide some guidance:
https://github.com/evilC/AutoHotInterception
from ahk.
That project also requires the installation of Interception and the whole point of that project is to avoid using AHK.
from ahk.
Since we already have the python keyboard project for creating powerful hotkeys from scratch, maybe a useful goal for this project is to incorporate hotkey functionality in a way that makes it as easy as possible to port existing autohotkey hotkeys to this framework.
I agree. Implementing the same functionality of keyboard
in this AHK wrapper is low-priority, in my view. If this library will provide Python callbacks to hotkeys, I would like to see it provide some added value, compared to using the keyboard
project.
incorporate hotkey functionality in a way that makes it as easy as possible to port existing autohotkey hotkeys to this framework.
Perhaps we can utilize keyboard
as in a dependency in some way and provide a uniform interface to creating keyboard
-based hotkeys and AHK hotkeys. Is that close to what you had in mind @gtusr ?
The idea might resemble something like the following:
class Hotkey(AHK):
def __init__(self, hotkey, ahk_script='', callback=None):
if ahk_script:
# create autohotkey-based hotkey
if callback: # a python callable
# create hotkey using the keyboard module
from ahk.
Should the hotkeys be blocking as they are in AHK with keyboard.block_key
, or maybe make it up to the user with default set to block? When a hotkey is called does the script that might run be blocking? Do you want a hotkey.bind
function?
(I know I am asking a lot of questions, but I would like to work on an implementation, and am wondering how it should be implemented)
from ahk.
from ahk.
@dequation in the current implementation, you can run #Persistent scripts nonblocking. Though, the concurrency is achieved by creating separate processes, not threads.
Hotkeys currently also run in the background and do not block script execution.
from ahk import AHK
ahk = AHK()
my_script = """
#Persistent
; the rest of the script
"""
process = ahk.run_script(my_script, blocking=False) # starts script in separate process and returns immediately
if the blocking
argument is set to True
, (the default) it will wait for the subprocess to complete. In short, when blocking=True
subprocess.run
is used. When blocking=False
, subprocess.Popen
is used.
Was there some other use case you have that is not satisfied currently?
from ahk.
Does keyboard allow for hotkeys that catch mouse buttons like ahk?
from ahk.
There is a counterpart mouse
module with similar capabilities. Both projects are mentioned towards the end of the README for this project.
from ahk.
do you want both in the project?
from ahk.
I'm not sure yet if we'll want to use either in the project or not. It's up for discussion at this point.
Personally, I think I want to limit the scope of how the library interacts with Hotkeys to AHK functionality. That is to say, not introduce a new way to create hotkeys utilizing additional libraries other than AHK. At least initially.
In the meantime, if users need Python callbacks for hotkeys, I think that directing users to use keyboard
or mouse
for that is OK for now.
(again, personally) I think, the next step towards this library supporting python callbacks for hotkeys is this:
- Develop an IPC solution for communication between AHK and Python (this has multiple applications beyond just hotkey callbacks)
- Leverage that solution to support python callbacks
Essentially, what #57 may aim to do.
But I'm open to other ideas or contributions.
from ahk.
I am not experienced enough with ahk to make a websocket solution. But I can make file based data transfer easily enough.
EDIT: I just found this post where this is said
"I have managed to make communication work in one direction: to the autohotkey script (with pywin32's SendMessage() and ahk's OnMessage(). The other direction has proved more difficult."
This might be worth looking into.
Although it looks like he is literally just writing to the same RAM memory location which is really dangerous for an OS. It is a possibility to allocate what would be needed in python, then construct and run an ahk template with the memory address saved.
from ahk.
Then there is also this file in a rather large github repo
https://github.com/majkinetor/mm-autohotkey/blob/master/IPC/IPC.ahk
It is a header file for ahk and DotNet that send data to a port.
This program just uses SendMessage.
from ahk.
incorporate hotkey functionality in a way that makes it as easy as possible to port existing autohotkey hotkeys to this framework.
Perhaps we can utilize
keyboard
as in a dependency in some way and provide a uniform interface to creatingkeyboard
-based hotkeys and AHK hotkeys. Is that close to what you had in mind @gtusr ?The idea might resemble something like the following:
class Hotkey(AHK): def __init__(self, hotkey, ahk_script='', callback=None): if ahk_script: # create autohotkey-based hotkey if callback: # a python callable # create hotkey using the keyboard module
This is likely the best approach because it provides the flexibility to create new hotkeys using callbacks while still also allowing us to leverage our prior familiarity with AHK hotkey syntax when appropriate, along with the vast library of useful AHK-based hotkey functions that has been created and distributed through various online forums over the past twenty years.
Just speaking for myself of course, but what I'd like to see most here is a complete representation of AHK hotkey syntax in the first branch (if ahk_script) so that AHK scripts can be ported over as easily as possible. The syntax and semantics of the AHK programming language itself leaves a lot to be desired, and many would no doubt prefer to use python instead. But the specialized syntax for describing keyboard events (and their combinations) may be something worth trying to preserve and even replicate in as faithful a manner as possible.
from ahk.
@spyoungtech I'm not sure how I'm supposed to use the Hotkey class. I create and then start the hotkey but it never seems to be usable. Using debug logging, it seems it adds an ExitApp statement which makes the script terminate immediately.
from ahk.
@AdrienHorgnies the hotkey class itself will keep the script running until stop
is called.
A few things to keep in mind:
- If your python script terminates, so will the hotkey; hotkeys do not block.
- The hotkey and script arguments use AutoHotkey syntax.
- Errors within the script are likely to pass silently
Try running the following script:
import time
from ahk import AHK, Hotkey
ahk = AHK()
notepad_hotkey = Hotkey(engine=ahk, hotkey='#n', script='Run Notepad')
notepad_hotkey.start()
while True:
time.sleep(10) # sleep forever to prevent script from ending prematurely
While this script is running if you press + n you should see the notepad application open.
from ahk.
Indeed, I didn't use the feature as intended. It works.
I was trying Hotkey(engine=ahk, hotkey='e', script='d')
but I should have tried Hotkey(engine=ahk, hotkey='e', script='Send, {d}')
.
from ahk.
Python callbacks for hotkeys are on the way as part of asyncio support #104
from ahk.
Hey @spyoungtech I love the library it is exactly what I needed. Is there a way to start an event loop so the app doesn't close immediately after execution? Also it could be used to check the state of keys so hotkeys would have much better functionality. Currently I am doing it with a while loop but it is not very elegant or effecient
hotkey = Hotkey(ahk, "my key combo", "my script")
try:
while True:
if ahk.key_state("Control") and ahk.key_state("Shift") and ahk.key_state("1"):
try:
print("Stopping timer script!")
hotkey.stop()
continue
except RuntimeError:
print("Hotkey is not running!!")
except KeyboardInterrupt:
print("Exiting")
os._exit(1)
Also what would be the proper way to close the ahk executable on exit cause it sometimes is left active even after my python script stops?
If needed I will open new thread but I feel it is directly related to this one.
Thanks in advance
from ahk.
@spyoungtech Thanks for the tips.
I thought I had to use os_exit(1)
because a similar module called keyboard launches functions in separate threads so that's the only way to kill the main thread.
The while loop actually works fine after I added micro sleep intervals to it sleep(0.01)
before it constantly used 100% of 1 core on CPU. Something like wait_forever
would be nice to have.
if ahk.key_state("Control") and ahk.key_state("Shift") and ahk.key_state("1")
wasn't really working reliably for some reason, often times it didn't detect properly so now I had to use keyboard module along ahk to detect keypresses which is not ideal but it works.
If you could implement async python callbacks that would be amazing. Keep up the good work!
from ahk.
@maracko If you must use os._exit(1)
, you can try putting hotkey.stop()
just beforehand to try to ensure cleanup of the hotkey process.
wasn't really working reliably for some reason
I imagine because there's quite a bit of latency to execute all three keystate checks. On my own system, it takes between 1/5 and 1/3 of a second to do all three checks. Might be slower in other systems/conditions. So, you'd probably have to hold all keys down for a while, which is not ideal.
Things like the daemon mode in #111 would help with that.... but I think the real solution would probably be hotkeys with python callbacks, similar to what keyboard
does. So, look forward to that!
from ahk.
I did something similar when I found I better to program my quite complex script in Python instead of AHK language. Obviously, I needed hotkeys to run my python functions that utilize my mouse and keyboard.
So, it works like that:
I add hotkeys like that:
hotkeys.on(['Alt', 'w'], start)
hotkeys.on(['Alt', 'e'], pause)
hotkeys.on(['Alt', 's'], open)
hotkeys.on(['Alt', 't'], test)
Here's on
function (in my hotkeys
module)
hots = []
def on(keys, func):
global hots
hots += [(keys, func)]
Here's where everything handled (I'm just checking in a loop using keyboard
that these keys are pressed):
I added sleep(1)
as a hotfix so that the script won't run 10 times while I'm pressing the keys. It works for me, so I didn't change it to a proper solution. Also, I quit all scripts by Alt+q combination right there.
def waiting():
while True:
alt = keyboard.is_pressed('Alt')
q = keyboard.is_pressed('q')
if alt and q:
break
for hot in hots:
if all(keyboard.is_pressed(i) for i in hot[0]):
Thread(target=hot[1], daemon=True).start()
sleep(1)
break
sleep(0.01)
In case someone wanted to do something similar without support from this lib.
from ahk.
Python callbacks coming with v1 #185
(available now, if you install from the PR source branch)
from ahk.
Hotkeys with Python callbacks now released in v1
from ahk.
Related Issues (20)
- [help wanted] Opposite method of block_forever()? HOT 3
- How to implement HotIf WinActive HOT 1
- ControlSend works in AHK script but does not work in Python HOT 1
- Howt to get the Cursor shape? HOT 1
- cannot assign values to global variables in callbacks HOT 3
- The mouse teleports instead of moving at a defined speed HOT 1
- hotkeys still keeps running if python process exits HOT 5
- AhkExecutableNotFoundError suddenly HOT 5
- mouse_drag method errors with "Invalid index.. Specifically: 8" HOT 2
- key_wait method does not work as expected
- ahk to arrange windows up and down HOT 4
- Why is window.id a string? HOT 5
- Hide tray icon at runtime HOT 3
- Tray menu and tooltips don't appear unless AHK executor is "stimulated" HOT 5
- Window.from_pid() not working HOT 10
- Invalid Index when calling `key_state()` in v2 HOT 2
- After locating a window, unable to send key presses to window. HOT 3
- win_move does not work in AutoHotkey v2 unless width and height are specified
- Ability to use HWND to target controls in Control methods
- detect_hidden_windows does not work as expected in some cases when using AutoHotkey v2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ahk.