¿Cómo puedo enviar comandos de teclado (mantener, liberar, simultáneamente) con una secuencia de comandos de python?

Quiero enviar virtualmente el comando así:

when keypress=="a" #if entered key is "a" send {ALT+TAB} # send ALT and TAB simultaneously sleep(2) #wait for 2 sec send {"I love my Country",0.1} #send all strings at 0.1 sec wait key_down("BACKSPACE",1) #hold down backspace key for 1 sec send{ALT+F4} #send ALT and F4 simultaneously 

Para todos, o una aplicación particular, también los juegos de opengl.

Intenté SendKeys.py pero no hay una función de entrada simultánea ni un método key_down para enviar presionando un comando de tecla. Todos los consejos serán muy apreciados.

Sé cómo hacerlo con ctypes. Por ejemplo, para Alt-Tab (es un montón de código repetitivo, lo sé):

 import ctypes import time SendInput = ctypes.windll.user32.SendInput PUL = ctypes.POINTER(ctypes.c_ulong) class KeyBdInput(ctypes.Structure): _fields_ = [("wVk", ctypes.c_ushort), ("wScan", ctypes.c_ushort), ("dwFlags", ctypes.c_ulong), ("time", ctypes.c_ulong), ("dwExtraInfo", PUL)] class HardwareInput(ctypes.Structure): _fields_ = [("uMsg", ctypes.c_ulong), ("wParamL", ctypes.c_short), ("wParamH", ctypes.c_ushort)] class MouseInput(ctypes.Structure): _fields_ = [("dx", ctypes.c_long), ("dy", ctypes.c_long), ("mouseData", ctypes.c_ulong), ("dwFlags", ctypes.c_ulong), ("time",ctypes.c_ulong), ("dwExtraInfo", PUL)] class Input_I(ctypes.Union): _fields_ = [("ki", KeyBdInput), ("mi", MouseInput), ("hi", HardwareInput)] class Input(ctypes.Structure): _fields_ = [("type", ctypes.c_ulong), ("ii", Input_I)] def PressKey(hexKeyCode): extra = ctypes.c_ulong(0) ii_ = Input_I() ii_.ki = KeyBdInput( hexKeyCode, 0x48, 0, 0, ctypes.pointer(extra) ) x = Input( ctypes.c_ulong(1), ii_ ) ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x)) def ReleaseKey(hexKeyCode): extra = ctypes.c_ulong(0) ii_ = Input_I() ii_.ki = KeyBdInput( hexKeyCode, 0x48, 0x0002, 0, ctypes.pointer(extra) ) x = Input( ctypes.c_ulong(1), ii_ ) ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x)) def PressAltTab(): PressKey(0x012) #Alt PressKey(0x09) #Tab time.sleep(2) #optional : if you want to see the atl-tab overlay ReleaseKey(0x09) #~Tab ReleaseKey(0x012) #~Alt if __name__ =="__main__": PressAltTab() 

Una versión moderna usaría Unicode:

KEYEVENTF_UNICODE = 0x0004 KEYEVENTF_KEYUP = 0x0002

 def PressKey(KeyUnicode): extra = ctypes.c_ulong(0) ii_ = Input_I() ii_.ki = KeyBdInput( 0, KeyUnicode, KEYEVENTF_UNICODE, 0, ctypes.pointer(extra) ) x = Input( ctypes.c_ulong(1), ii_ ) ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x)) def ReleaseKey(KeyUnicode): extra = ctypes.c_ulong(0) ii_ = Input_I() ii_.ki = KeyBdInput( 0, KeyUnicode, KEYEVENTF_UNICODE|KEYEVENTF_KEYUP, 0, ctypes.pointer(extra) ) x = Input( ctypes.c_ulong(1), ii_ ) ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x)) def PressAltTab(): PressKey(unichr(0x12)) #Alt PressKey(unichr(0x09)) #Tab time.sleep(2) #optional : if you want to see the atl-tab overlay ReleaseKey(unichr(0x09)) #~Tab ReleaseKey(unichr(0x12)) #~Alt if __name__ =="__main__": PressAltTab()