keyboard icon indicating copy to clipboard operation
keyboard copied to clipboard

keyboard.write doesn't actually press any key

Open NobodyXu opened this issue 3 years ago • 4 comments

When I run my script:

#!/usr/bin/env python3

import keyboard

keyboard.write('a')

keyboard.write('a')

as root in linux, nothing happened:

$ sudo ./keyboardPressSimulator.py
$

If I typed this in the python interpreter directly, then from the second write, the program is actually able to simulate key press:

$ sudo python3                     
Python 3.8.8 (default, Apr 23 2021, 11:49:15)                          
[Clang 11.1.0 ] on linux                                               
Type "help", "copyright", "credits" or "license" for more information. 
>>> import keyboard                                                    
>>> keyboard.write("h")                                                
>>> keyboard.write("h")                                                
>>> h                                                                  
Traceback (most recent call last):                                     
  File "<stdin>", line 1, in <module>                                  
NameError: name 'h' is not defined                                     
>>> keyboard.write("h")                                                
>>> h                                                                  
Traceback (most recent call last):                                     
  File "<stdin>", line 1, in <module>                                  
NameError: name 'h' is not defined                                     
>>>                                                                    
$                                  

I also tried record and play, somehow they worked on my system.

But if I tried to call play with hand crafted events, that doesn't work:

def createEvent(ch, event_type):
    """
    @param event_type either "up" or "down"
    """
    scan_code = keyboard.key_to_scan_codes(ch)[0]
    return keyboard.KeyboardEvent(event_type, scan_code, name = ch, modifiers = tuple(), is_keypad = False)

def press(ch):
    keyboard.play([createEvent(ch, keyboard.KEY_DOWN), createEvent(ch, keyboard.KEY_UP)])

press('a')
press('b')

I also found that keyboard.press works in the script, but the first keyboard.press does nothing:

#!/usr/bin/env python3

import keyboard
import time

def simulate(ch):
    key = keyboard.key_to_scan_codes(ch)[0]
    keyboard.press(key)
    time.sleep(1)
    keyboard.release(key)
    time.sleep(1)

simulate("a")
simulate("b")
simulate("a")

gives:

$ sudo ./keyboardPressSimulator.py
bbbbbbbbbbbaaaaaaaaaaa$

System info

os:

NAME=Gentoo                                   
ID=gentoo                                     
PRETTY_NAME="Gentoo/Linux"                    
ANSI_COLOR="1;32"                             
HOME_URL="https://www.gentoo.org/"            
SUPPORT_URL="https://www.gentoo.org/support/" 
BUG_REPORT_URL="https://bugs.gentoo.org/"

Kernel:

Linux gentoo 5.11.16-gentoo #2 SMP Fri Apr 23 21:01:39 AEST 2021 x86_64 Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz GenuineIntel GNU/Linux                                                                     

interpreter:

cpython 3.8.8

package keyboard version:

0.13.5

NobodyXu avatar Apr 23 '21 11:04 NobodyXu

This all works for me on custom linuxOS between Ubunutu and Kali. I feel this is something to do with your setup. Try not using Cpython and just Python3 latest, see if that works first. Then start looking at the compiler for your desired version of Cpython and see if it is mangling something. Just something I would look at. Good luck!

lnfjobs avatar May 03 '21 19:05 lnfjobs

Yeah, I can reproduce this as well. What I found is that it seems that the first keypress in a script does not work and it takes a second after the first keyboard.write() to actually work and start sending keys correctly.

So, this works:

import keyboard
import time

# initialize keyboard module
keyboard.press_and_release('alt')
time.sleep(0.1)

# now you can actually send something
keyboard.write('hello')

If you remove the sleep() or set a sleep time that's too short, then keyboard may skip the first few characters you write(). There's nothing special about pressing alt, but as long as you start simulating key press, the startup timer begins.

I'm guessing that keyboard was initializing its background threads in the first simulated key press, and it missed all the simulated key presses that's supposed to be happening during the thread initialization.

lieryan avatar Jul 15 '21 14:07 lieryan

This all works for me on custom linuxOS between Ubunutu and Kali. I feel this is something to do with your setup. Try not using Cpython and just Python3 latest, see if that works first. Then start looking at the compiler for your desired version of Cpython and see if it is mangling something. Just something I would look at. Good luck!

Cpython is the name of the official implementation of python3, so I am indeed running python3.

NobodyXu avatar Jul 16 '21 02:07 NobodyXu

ive had the same issue on linux: manjaro i3 (arch derivitive). as lieryan mentioned, it seemed to need to be initialized first. so i dug through the code to see what might be causing it. i couldnt find the source of the issue, but a suitable solution.

theres an internal init function that can be called keyboard._os_keyboard.init() following that with a short delay of 100ms appeared to work, without needing to send superfluous key-strokes.

it seems clunky to refrence internal functions outside of the module, so i added this bit of code inside the modules init.py just under where _os_keyboard is defined. _os_keyboard.init() _time.sleep(0.1)

ran my code again, and no issues; works as intended. though still needs testing on other systems. ill push changes to a new branch once i can figure out githubs new token sillyness

arainflake avatar Sep 17 '21 19:09 arainflake