Un envoltorio de pitón completamente escrito alrededor de Autohotkey.
pip install ahk
Requiere Python 3.8+
Admite AutoHotKey V1 y V2. Ver también: Dependencias que no son de Python
from ahk import AHK
ahk = AHK ()
ahk . mouse_move ( x = 100 , y = 100 , blocking = True ) # Blocks until mouse finishes moving (the default)
ahk . mouse_move ( x = 150 , y = 150 , speed = 10 , blocking = True ) # Moves the mouse to x, y taking 'speed' seconds to move
print ( ahk . mouse_position ) # (150, 150)Ejemplos no exhaustivos de algunas funciones disponibles con este paquete. Consulte la documentación completa para referencias de API completas y características adicionales.
Las teclas de acceso rápido se pueden configurar para ejecutar funciones de Python como devoluciones de llamada.
Por ejemplo:
from ahk import AHK
def my_callback ():
print ( 'Hello callback!' )
ahk = AHK ()
# when WIN + n is pressed, fire `my_callback`
ahk . add_hotkey ( '#n' , callback = my_callback )
ahk . start_hotkeys () # start the hotkey process thread
ahk . block_forever () # not strictly needed in all scripts -- stops the script from exiting; sleep forever Ahora cuando presionas + n , la función de devolución de llamada my_callback se llamará en un hilo de fondo.
También puede agregar un controlador de excepción para su devolución de llamada:
from ahk import AHK
ahk = AHK ()
def go_boom ():
raise Exception ( 'boom!' )
def my_ex_handler ( hotkey : str , exception : Exception ):
print ( 'exception with callback for hotkey' , hotkey , 'Here was the error:' , exception )
ahk . add_hotkey ( '#n' , callback = go_boom , ex_handler = my_ex_handler )También hay métodos para eliminar las teclas de acceso rápido:
# ...
ahk . remove_hotkey ( '#n' ) # remove a hotkey by its keyname
ahk . clear_hotkeys () # remove all hotkeysTenga en cuenta que:
ahk.start_hotkeys() )ahk.stop_hotkeys() (no dejará de ejecutar activamente devoluciones de llamada)Ver también la documentación correspondiente de AHK
También se pueden agregar hotstrings al hilo del proceso de tecla hot.
Además de los hotstrings que admiten reemplazos normales de cadenas AHK, también puede proporcionar devoluciones de llamada de Python (con manejadores de excepción opcionales) en respuesta a la activación de hotstrings.
from ahk import AHK
ahk = AHK ()
def my_callback ():
print ( 'hello callback!' )
ahk . add_hotstring ( 'btw' , 'by the way' ) # string replacements
ahk . add_hotstring ( 'btw' , my_callback ) # call python function in response to the hotstringTambién puede eliminar los hotstrings:
ahk . remove_hotstring ( 'btw' ) # remove a hotstring by its trigger sequence
ahk . clear_hotstrings () # remove all registered hotstrings from ahk import AHK
ahk = AHK ()
ahk . mouse_position # Returns a tuple of mouse coordinates (x, y) (relative to active window)
ahk . get_mouse_position ( coord_mode = 'Screen' ) # get coordinates relative to the screen
ahk . mouse_move ( 100 , 100 , speed = 10 , relative = True ) # Moves the mouse reletave to the current position
ahk . mouse_position = ( 100 , 100 ) # Moves the mouse instantly to absolute screen position
ahk . click () # Click the primary mouse button
ahk . click ( 200 , 200 ) # Moves the mouse to a particular position and clicks (relative to active window)
ahk . click ( 100 , 200 , coord_mode = 'Screen' ) # click relative to the screen instead of active window
ahk . click ( button = 'R' , click_count = 2 ) # Clicks the right mouse button twice
ahk . right_click () # Clicks the secondary mouse button
ahk . mouse_drag ( 100 , 100 , relative = True ) # Holds down primary button and moves the mouse from ahk import AHK
ahk = AHK ()
ahk . type ( 'hello, world!' ) # Send keys, as if typed (performs string escapes for you)
ahk . send_input ( 'Hello, {U+1F30E}{!}' ) # Like AHK SendInput
# Unlike `type`, control sequences must be escaped manually.
# For example the characters `!^+#=` and braces (`{` `}`) must be escaped manually.
ahk . key_state ( 'Control' ) # Return True or False based on whether Control key is pressed down
ahk . key_state ( 'CapsLock' , mode = 'T' ) # Check toggle state of a key (like for NumLock, CapsLock, etc)
ahk . key_press ( 'a' ) # Press and release a key
ahk . key_down ( 'Control' ) # Press down (but do not release) Control key
ahk . key_up ( 'Control' ) # Release the key
ahk . set_capslock_state ( "On" ) # Turn CapsLock on
if ahk . key_wait ( 'x' , timeout = 3 ): # wait for a key to be pressed; returns a boolean
print ( 'X was pressed within 3 seconds' )
else :
print ( 'X was not pressed within 3 seconds' )También puedes hacer cosas con Windows.
from ahk import AHK
ahk = AHK ()
win = ahk . active_window # Get the active window
win = ahk . win_get ( title = 'Untitled - Notepad' ) # by title
all_windows = ahk . list_windows () # list of all windows
win = ahk . win_get_from_mouse_position () # the window under the mouse cursor
win = ahk . win_get ( title = 'ahk_pid 20366' ) # get window from pid
# Wait for a window
try :
# wait up to 5 seconds for notepad
win = ahk . win_wait ( title = 'Untitled - Notepad' , timeout = 5 )
# see also: win_wait_active, win_wait_not_active
except TimeoutError :
print ( 'Notepad was not found!' ) from ahk import AHK
ahk = AHK ()
ahk . run_script ( 'Run Notepad' ) # Open notepad
win = ahk . find_window ( title = 'Untitled - Notepad' ) # Find the opened window; returns a `Window` object
# Window object methods
win . send ( 'hello' , control = 'Edit1' ) # Send keys directly to the window (does not need focus!)
# OR ahk.control_send(title='Untitled - Notepad', control='Edit1')
win . move ( x = 200 , y = 300 , width = 500 , height = 800 )
win . activate () # Give the window focus
win . close () # Close the window
win . hide () # Hide the window
win . kill () # Kill the window
win . maximize () # Maximize the window
win . minimize () # Minimize the window
win . restore () # Restore the window
win . show () # Show the window
win . disable () # Make the window non-interactable
win . enable () # Enable it again
win . to_top () # Move the window on top of other windows
win . to_bottom () # Move the window to the bottom of the other windows
win . get_class () # Get the class name of the window
win . get_minmax () # Get the min/max status
win . get_process_name () # Get the process name (e.g., "notepad.exe")
win . process_name # Property; same as `.get_process_name()` above
win . is_always_on_top () # Whether the window has the 'always on top' style applied
win . list_controls () # Get a list of controls (list of `Control` objects)
win . redraw () # Redraw the window
win . set_style ( "-0xC00000" ) # Set a style on the window (in this case, removing the title bar)
win . set_ex_style ( "^0x80" ) # Set an ExStyle on the window (in this case, removes the window from alt-tab list)
win . set_region ( "" ) # See: https://www.autohotkey.com/docs/v2/lib/WinSetRegion.htm
win . set_trans_color ( "White" ) # Makes all pixels of the chosen color invisible inside the specified window.
win . set_transparent ( 155 ) # Makes the specified window semi-transparent (or "Off" to turn off transparency)
win . always_on_top = 'On' # Make the window always on top
# or
win . set_always_on_top ( 'On' )
for window in ahk . list_windows (): # list all (non-hidden) windows -- ``detect_hidden_windows=True`` to include hidden
print ( window . title )
# Some more attributes
print ( window . text ) # window text -- or .get_text()
print ( window . get_position ()) # (x, y, width, height)
print ( window . id ) # the ahk_id of the window
print ( window . pid ) # process ID -- or .get_pid()
print ( window . process_path ) # or .get_process_path()
if win . active : # or win.is_active()
...
if win . exist : # or win.exists()
...
# Controls
edit_control = win . list_controls ()[ 0 ] # get the first control for the window, in this case "Edit1" for Notepad
edit_control . get_text () # get the text in Notepad
edit_control . get_position () # returns a `Postion` namedtuple: e.g. Position(x=6, y=49, width=2381, height=1013) Varios métodos de ventana también se pueden llamar directamente sin crear primero un objeto Window utilizando los métodos win_* subyacentes en la clase AHK . Por ejemplo, en lugar de win.close() como se indicó anteriormente, se podría llamar ahk.win_close(title='Untitled - Notepad') en su lugar.
from ahk import AHK
ahk = AHK ()
ahk . image_search ( 'C: \ path \ to \ image.jpg' ) # Find an image on screen
# Find an image within a boundary on screen
ahk . image_search ( 'C: \ path \ to \ image.jpg' , upper_bound = ( 100 , 100 ), # upper-left corner of search area
lower_bound = ( 400 , 400 )) # lower-right corner of search area
ahk . pixel_get_color ( 100 , 100 ) # Get color of pixel located at coords (100, 100)
ahk . pixel_search ( color = '0x9d6346' , search_region_start = ( 0 , 0 ), search_region_end = ( 500 , 500 )) # Get coords of the first pixel with specified color Obtener/establecer datos Clipboard
from ahk import AHK
ahk = AHK ()
ahk . set_clipboard ( 'hello N{EARTH GLOBE AMERICAS} ' ) # set clipboard text contents
ahk . get_clipboard () # get clipboard text contents
# 'hello ?'
ahk . set_clipboard ( "" ) # Clear the clipboard
ahk . clip_wait ( timeout = 3 ) # Wait for clipboard contents to change (with text or file(s))
ahk . clip_wait ( timeout = 3 , wait_for_any_data = True ) # wait for _any_ clipboard contents También puede obtener/establecer ClipboardAll ; sin embargo, nunca debe intentar llamar set_clipboard_all con cualquier otro datos que no sean exactamente como lo devuelven get_clipboard_all o pueden ocurrir problemas inesperados.
from ahk import AHK
ahk = AHK ()
# save all clipboard contents in all formats
saved_clipboard = ahk . get_clipboard_all ()
ahk . set_clipboard ( 'something else' )
...
ahk . set_clipboard_all ( saved_clipboard ) # restore saved content from earlier También puede establecer una devolución de llamada para ejecutar cuando cambia el contenido del portapapeles. Al igual que con los métodos de tecla de acceso rápido mencionados anteriormente, también puede establecer un controlador de excepción. Al igual que las teclas de acceso rápido, las devoluciones de llamada on_clipboard_change también requieren .start_hotkeys() para que se llame para entrar en vigencia.
La función de devolución de llamada debe aceptar un argumento posicional, que es un entero que indica el tipo de datos del portapapeles.
from ahk import AHK
ahk = AHK ()
def my_clipboard_callback ( change_type : int ):
if change_type == 0 :
print ( 'Clipboard is now empty' )
elif change_type == 1 :
print ( 'Clipboard has text contents' )
elif change_type == 2 :
print ( 'Clipboard has non-text contents' )
ahk . on_clipboard_change ( my_clipboard_callback )
ahk . start_hotkeys () # like with hotkeys, must be called at least once for listening to start
# ...
ahk . set_clipboard ( "hello" ) # will cause the message "Clipboard has text contents" to be printed by the callback
ahk . set_clipboard ( "" ) # Clears the clipboard, causing the message "Clipboard is now empty" to be printed by the callback from ahk import AHK
ahk = AHK ()
ahk . sound_play ( 'C: \ path \ to \ sound.wav' ) # Play an audio file
ahk . sound_beep ( frequency = 440 , duration = 1000 ) # Play a beep for 1 second (duration in microseconds)
ahk . get_volume ( device_number = 1 ) # Get volume of a device
ahk . set_volume ( 50 , device_number = 1 ) # Set volume of a device
ahk . sound_get ( device_number = 1 , component_type = 'MASTER' , control_type = 'VOLUME' ) # Get sound device property
ahk . sound_set ( 50 , device_number = 1 , component_type = 'MASTER' , control_type = 'VOLUME' ) # Set sound device property Tray -tips/bansytips
import time
from ahk import AHK
ahk = AHK ()
ahk . show_tooltip ( "hello4" , x = 10 , y = 10 )
time . sleep ( 2 )
ahk . hide_tooltip () # hide the tooltip
ahk . show_info_traytip ( "Info" , "It's also info" , silent = False , blocking = True ) # Default info traytip
ahk . show_warning_traytip ( "Warning" , "It's a warning" ) # Warning traytip
ahk . show_error_traytip ( "Error" , "It's an error" ) # Error trytipCuadros de diálogo
from ahk import AHK , MsgBoxButtons
ahk = AHK ()
ahk . msg_box ( text = 'Do you like message boxes?' , title = 'My Title' , buttons = MsgBoxButtons . YES_NO )
ahk . input_box ( prompt = 'Password' , title = 'Enter your password' , hide = True )
ahk . file_select_box ( title = 'Select one or more mp3 files' , multi = True , filter = '*.mp3' , file_must_exist = True )
ahk . folder_select_box ( prompt = 'Select a folder' ) Puede cambiar varios estados globales, como CoordMode , DetectHiddenWindows , etc. para que no tenga que pasar estos parámetros directamente a las llamadas de funciones
from ahk import AHK
ahk = AHK ()
ahk . set_coord_mode ( 'Mouse' , 'Screen' ) # set default Mouse CoordMode to be relative to Screen
ahk . set_detect_hidden_windows ( True ) # Turn on detect hidden windows by default
ahk . set_send_level ( 5 ) # Change send https://www.autohotkey.com/docs/v1/lib/SendLevel.htm
ahk . set_title_match_mode ( 'Slow' ) # change title match speed and/or mode
ahk . set_title_match_mode ( 'RegEx' )
ahk . set_title_match_mode (( 'RegEx' , 'Slow' )) # or both at the same time
ahk . set_send_mode ( 'Event' ) # change the default SendMode Puede agregar directivas que se agregarán a todos los scripts generados. Por ejemplo, para evitar que aparezca el Trayicón AHK, puede agregar la Directiva NotReicon.
from ahk import AHK
from ahk . directives import NoTrayIcon
ahk = AHK ( directives = [ NoTrayIcon ])De forma predeterminada, algunas directivas se agregan automáticamente para garantizar la funcionalidad y se fusionan con las directivas proporcionadas por el usuario.
Las directivas no se aplican para el proceso AHK utilizado para manejar teclas de acceso rápido y hotstrings (discutidos a continuación) de forma predeterminada. Para aplicar una directiva al proceso de las teclas de acceso rápido utilizando el argumento de palabras clave apply_to_hotkeys_process=True :
from ahk import AHK
from ahk . directives import NoTrayIcon
directives = [
NoTrayIcon ( apply_to_hotkeys_process = True )
]
ahk = AHK ( directives = directives )Como se discutió anteriormente, puede ocultar el icono de la bandeja si lo desea. Además, hay algunos métodos disponibles para personalizar el icono de la bandeja.
from ahk import AHK
ahk = AHK ()
# change the tray icon (in this case, using a builtin system icon)
ahk . menu_tray_icon ( 'Shell32.dll' , 174 )
# revert it back to the original:
ahk . menu_tray_icon ()
# change the tooltip that shows up when hovering the mouse over the tray icon
ahk . menu_tray_tooltip ( 'My Program Name' )
# Hide the tray icon
ahk . menu_tray_icon_hide ()
# Show the tray icon that was previously hidden by ``NoTrayIcon`` or ``menu_tray_icon_hide``
ahk . menu_tray_icon_show ()Puede leer/escribir/eliminar claves de registro:
from ahk import AHK
ahk = AHK ()
ahk . reg_write ( 'REG_SZ' , r'HKEY_CURRENT_USERSOFTWAREmy-software' , value = 'test' )
ahk . reg_write ( 'REG_SZ' , r'HKEY_CURRENT_USERSOFTWAREmy-software' , value_name = 'foo' , value = 'bar' )
ahk . reg_read ( r'HKEY_CURRENT_USERSOFTWAREmy-software' ) # 'test'
ahk . reg_delete ( r'HKEY_CURRENT_USERSOFTWAREmy-software' )Si no existe una clave o se produce algún otro problema, se plantea una excepción.
La mayoría de los métodos en esta biblioteca proporcionan una interfaz sin bloqueo, para que sus scripts de Python puedan continuar ejecutándose mientras se ejecutan sus scripts AHK.
Por defecto, todas las llamadas están bloqueando : cada función se ejecutará completamente antes de que se ejecute la siguiente función.
Sin embargo, a veces es posible que desee ejecutar otro código mientras AHK ejecuta algún código. Cuando el argumento de palabras clave blocking se suministra con False , las llamadas de funciones volverán inmediatamente mientras la función AHK se lleva a cabo en segundo plano.
Como ejemplo, puede mover el mouse lentamente e informar su posición a medida que se mueve:
import time
from ahk import AHK
ahk = AHK ()
ahk . mouse_position = ( 200 , 200 ) # Moves the mouse instantly to the start position
start = time . time ()
# move the mouse very slowly
ahk . mouse_move ( x = 100 , y = 100 , speed = 30 , blocking = False )
# This code begins executing right away, even though the mouse is still moving
while True :
t = round ( time . time () - start , 4 )
position = ahk . mouse_position
print ( t , position ) # report mouse position while it moves
if position == ( 100 , 100 ):
break Cuando especifique blocking=False siempre recibirá un objeto Special FutureResult (o el objeto AsyncFutureResult en la API Async, que se analiza a continuación) que le permite esperar la función para completar y recuperar el valor de retorno a través de una función get_result . Incluso cuando una función normalmente no devuelve None , esto puede ser útil para garantizar que AHK haya terminado de ejecutar la función.
Llamadas sin bloqueo:
set_coord_mode o similar): esto puede cambiar en una versión futura.FutureResult (o el objeto AsyncFutureResult en la API Async, que se discute a continuación) que le permite esperar la función para completar y recuperar el valor de retorno a través de la función result . Incluso cuando una función normalmente no devuelve None , esto puede ser útil para garantizar que AHK haya terminado de ejecutar la función. from ahk import AHK
ahk = AHK ()
future_result = ahk . mouse_move ( 100 , 100 , speed = 40 , blocking = False )
...
# wait on the mouse_move to finish
future_result . result ( timeout = 10 ) # timeout keyword is optional Se proporciona una API de Async para que las funciones se puedan llamar usando async / await . Todos los mismos métodos de la API sincrónica están disponibles en la API Async.
from ahk import AsyncAHK
import asyncio
ahk = AsyncAHK ()
async def main ():
await ahk . mouse_move ( 100 , 100 )
x , y = await ahk . get_mouse_position ()
print ( x , y )
asyncio . run ( main ())La API Async es idéntica a la de la API normal, con algunas diferencias notables:
.mouse_position o .title para Windows) se pueden await , se pueden esperar métodos adicionales (como get_mouse_position() y get_title() ) para una API más intuitiva y se recomiendan sobre el uso de propiedades.ahk.mouse_postion = (200, 200) ) no están permitidos en la API Async (se eleva un TimeError de ejecución). Los establecedores de propiedades permanecen disponibles en la API de sincronización.AsyncFutureResult (devueltos al especificar blocking=False ) funcionan lo mismo que los objetos FutureResult en la API de sincronización, excepto que la palabra clave timeout no es compatible con el método result ).Tenga en cuenta también que:
AsyncAHK no se ejecutarán simultáneamente. Debe usar blocking=False , como en la API de sincronización, o usar múltiples instancias de AsyncAHK . Esta biblioteca es totalmente con sugerencia, lo que le permite aprovechar herramientas como mypy para ayudar a validar la corrección de tipos de su código. Los IDE que implementan funciones de verificación de tipo también pueden aprovechar sugerencias de tipo para ayudar a garantizar que su código sea seguro.
También puede ejecutar el código arbitrary autohotkey como un archivo de script .ahk o como una cadena que contiene código AHK.
from ahk import AHK
ahk = AHK ()
my_script = '''
MouseMove, 100, 100
; etc...
'''
ahk . run_script ( my_script ) from ahk import AHK
ahk = AHK ()
script_path = r'C:PathTomyscript.ahk'
ahk . run_script ( script_path ) Para usar este paquete, necesita el ejecutable AutoHotkey (por ejemplo, AutoHotkey.exe ). Se espera que esté en ruta de forma predeterminada o en una ubicación de instalación predeterminada ( C:Program FilesAutoHotkeyAutoHotkey.exe para v1 o C:Program FilesAutoHotkeyv2AutoHotkey64.exe para v2)
Autohotkey V1 y V2 son totalmente compatibles, aunque se producirán algunas diferencias de comportamiento dependiendo de la versión que use. Vea las notas a continuación.
La forma recomendada de suministrar el binario AutoHotkey (tanto para V1 como V2) es instalar el binary extra para este paquete. Esto proporcionará los ejecutables necesarios y ayudará a garantizar que se coloquen correctamente en la ruta.
pip install "ahk[binary]"
Alternativamente, puede proporcionar la ruta en el código:
from ahk import AHK
ahk = AHK ( executable_path = 'C: \ path \ to \ AutoHotkey.exe' ) También puede usar la variable de entorno AHK_PATH para especificar la ubicación ejecutable.
set AHK_PATH=C:PathToAutoHotkey.exe
python myscript.py De manera predeterminada, cuando no se establece el parámetro executable_path (o la variable de entorno AHK_PATH ), solo se buscan los nombres binarios AutoHotKey V1 en la ruta o las ubicaciones de instalación predeterminadas. Este comportamiento puede cambiar en futuras versiones para permitir que V2 se use de forma predeterminada.
Para usar autohotkey versión 2, puede hacer cualquiera de las siguientes cosas:
executable_path con la ubicación del binario AutoHotkey V2AHK_PATH con la ubicación de un binario AutoHotKey V2version con el valor v2 que permite encontrar el ejecutable utilizando nombres binarios AutoHotKey V2 y ubicaciones de instalación predeterminadas.Por ejemplo:
from ahk import AHK
ahk = AHK ( executable_path = r'C:Program FilesAutoHotkeyv2AutoHotkey64.exe' )
# OR
ahk = AHK ( version = 'v2' ) Cuando proporciona el argumento de palabras clave version (con "v1" o "v2" ), se realiza una verificación para garantizar que el binario proporcionado (o descubierto) coincida con la versión solicitada. Cuando se omite la palabra clave version , la versión se determina automáticamente a partir del binario ejecutable proporcionado (o descubierto).
La API de este proyecto se diseña originalmente contra AutoHotkey V1 y las firmas de funciones son las mismas, incluso cuando se usa AutoHotkey V2. Si bien la mayor parte del comportamiento sigue siendo el mismo, algún comportamiento cambia cuando se usa Autohotkey V2 en comparación con V1. Esto se debe principalmente a las diferencias subyacentes entre las dos versiones.
Algunas de las diferencias notables que puede experimentar al usar autohotkey V2 con esta biblioteca incluyen:
None (como en AutoHotkey V2, se lanza un TargetError en la mayoría de los casos donde no se puede encontrar la ventana o el control)ControlSend ( ahk.control_send o Window.send o Control.send ) difiere en autohotkey v2 cuando no se especifica el parámetro control . En V1, las claves se envían a los controles más altos, que generalmente es el comportamiento correcto. En V2, las teclas se envían directamente a la ventana. Esto significa que en muchos casos, debe especificar el control explícitamente cuando se usa V2.secondstowait parámetro de TrayTip ( ahk.show_traytip ) se eliminó en V2. Especificar este parámetro en el envoltorio de pitón hará que se emita una advertencia y se ignora el parámetro.Input en lugar del Event en V1 (como consecuencia, por ejemplo, los parámetros de velocidad del mouse a mouse_move y mouse_drag se ignorarán en V2 a menos que el modo de envío se cambie)2 en AutoHotKey V2. Es 1 en Autohotkey V1. Use los argumentos de palabras clave title_match_mode para win_get y otros métodos que aceptan esta palabra clave para controlar este comportamiento o use set_title_match_mode para cambiar el comportamiento predeterminado (las llamadas que no son de bloqueo se ejecutan en procesos separados y no se ven afectadas por set_title_match_mode ) Puede desarrollar extensiones para extender la funcionalidad de ahk , es decir: escribir su propio código autohotkey y agregar métodos adicionales a la clase AHK. Consulte los documentos extendidos para obtener más información.
Todas las contribuciones son bienvenidas y apreciadas.
No dude en abrir un problema de GitHub o un PR para comentarios, ideas, solicitudes de funciones o preguntas.
Estos son algunos proyectos similares que se usan comúnmente para la automatización con Python.
keyboard , Pure Python Mouse Control!