21

How can I simulate a keystroke in python? I also want to press multiple keys simultaneously.

Something like:

keystroke('CTRL+F4')

or

keystroke('Shift+A')
James Vickery
  • 732
  • 3
  • 10
  • 23
microo8
  • 3,568
  • 5
  • 37
  • 67

6 Answers6

18

Consider python-uinput and evdev. Example of shift+a with the latter:

from evdev import uinput, ecodes as e

with uinput.UInput() as ui:
    ui.write(e.EV_KEY, e.KEY_LEFTSHIFT, 1)
    ui.write(e.EV_KEY, e.KEY_A, 1)
    ui.syn()
gvalkov
  • 3,977
  • 30
  • 31
  • I tried similar code, it is exeuted because I see in system log that a new virtual input device was created but the keystrokes do not appear in X? Any special thing can be done so the keys are received by X server? – akostadinov Jul 05 '13 at 10:18
  • 1
    The links are dead – Mehdi Nellen Apr 06 '17 at 10:56
  • This is great! Note that 1 is a keydown event and 0 is keyup, so if you wanted to simulate a pressing and releasing a key more than once, you would need to place something like the following lines in a loop: `ui.write(ecodes.EV_KEY, ecodes.KEY_DOWN, 1) #key down` `ui.write(ecodes.EV_KEY, ecodes.KEY_DOWN, 0) #key up` `ui.syn()` – cmperezg Mar 13 '19 at 18:43
  • 2
    it gave me this error: `UInputError: "/dev/uinput" cannot be opened for writing` Any suggestion? – Alex Jun 14 '19 at 20:15
  • Adding `KERNEL=="uinput", MODE="0666` to the top of /etc/udev/rules.d/50-rogdrv.rules and reloading rules solves the problem" ([github issue](https://github.com/kyokenn/rogdrv/issues/5)) You can reload udev rules like this `# udevadm control --reload-rules && udevadm trigger` ([source](https://newbedev.com/how-to-reload-udev-rules-without-reboot)) – Yann Hoffmann Aug 10 '21 at 10:44
  • The example given only requires [evdev](https://python-evdev.readthedocs.io/en/latest/). After I did `pip install evdev`, I pasted the example into a python3 interpreter. It worked straight away. It may have helped that I already had the uinput kernel module loaded.- `modprobe uinput`. – Michael Hamilton Dec 01 '22 at 04:08
15

python-uinput:

Pythonic API to Linux uinput kernel module...

Python-uinput is Python interface to Linux uinput kernel module which allows attaching userspace device drivers into kernel. In practice, Python-uinput makes it dead simple to create virtual joysticks, keyboards and mice for generating arbitrary input events programmatically...

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
15

Although it's specific to X, you can install the xautomation package (apt-get install xautomation on Debian-based systems) and use xte to simulate keypresses, e.g.:

from subprocess import Popen, PIPE

control_f4_sequence = '''keydown Control_L
key F4
keyup Control_L
'''

shift_a_sequence = '''keydown Shift_L
key A
keyup Shift_L
'''

def keypress(sequence):
    p = Popen(['xte'], stdin=PIPE)
    p.communicate(input=sequence)

keypress(shift_a_sequence)
keypress(control_f4_sequence)
Mark Longair
  • 446,582
  • 72
  • 411
  • 327
4

If you plan to use it on Linux, try pyautogui library. For multiple keys you will need to use hotkey, e.g.:

pyautogui.hotkey('ctrl', 'c')  # ctrl-c to copy

For me it worked - see here: How to pass a keystroke (ALT+TAB) using Popen.communicate (on Linux)?

michalrudko
  • 1,432
  • 2
  • 16
  • 30
2

If you are on Windows, use Sendkeys and if on Linux, try out the suggestion given here for xsendkeys or pexpect.

Community
  • 1
  • 1
Senthil Kumaran
  • 54,681
  • 14
  • 94
  • 131
1

Simplest solution I have found was using pynput. You could do the following:

from pynput.keyboard import Key, Controller

keyboard = Controller()
with keyboard.pressed(Key.ctrl):
   keyboard.press(Key.f4)
   keyboard.release(Key.f4)
Eduardo
  • 4,282
  • 2
  • 49
  • 63