Infinite Loop When Using pynput to Replace Typed Letters with 'a'

64 Views Asked by At

I'm trying to create a python program to replace every letter typed with an a, but when I try it, it gets stuck in a loop because pyput also listens to the key presses it sends, and it gets stuck in a loop. I also tried to stop the thread before it pressed the key, and restart it after it releases it, but it was too slow. Here is the code:

from pynput.keyboard import Key, Controller
from pynput.keyboard import Listener as KeyboardListener
import pynput.keyboard._win32


keyboard = Controller()


def on_press(key):
    if type(key) == pynput.keyboard._win32.KeyCode:
        keyboard.press(Key.backspace)
        keyboard.release(Key.backspace)
        keyboard.press('a')
        keyboard.release('a')


keyboard_listener = KeyboardListener(on_press=on_press)
keyboard_listener.start()
keyboard_listener.join()
1

There are 1 best solutions below

0
5rod On

I think it is easier to use keyboard. You can easily detect a key press in a loop that does the desired function:

import keyboard

def replace_typed():
    keyboard.press_and_release('backspace')
    keyboard.press_and_release('a')

while True:
    if keyboard.read_key():
        replace_typed()

Only downside that I can see here is that it is stuck in a while loop, so if you want to do other functions during the time, you'll need to use threading or multiprocess, or asyncio. At least, it should get rid of the lag problem.

A little advice:

I did find that there is a keyboard.block_key() function to block all keys. You can do it like this:

import keyboard

for key in range(150):
    keyboard.block_key(key)

And it will block all keys. I would recommend being careful with this, because this literally disables your keyboard. You can still do virtual key presses however, and for some reason, pynput still detects your keyboard presses even though keyboard blocked it. So you won't have to use the pressing of backspace anymore. Now I had a few lag problems with this as well, but something like this is worth a try:

import keyboard
from pynput.keyboard import Listener

for key in range(150):
    keyboard.block_key(key) #blocks all keys

def onPress(key):
    if key.char == 's':
        exit() #fail safe I put in here if everything goes wrong
    
    keyboard.press_and_release('a') #presses a

with Listener(on_press = onPress) as listener:
    listener.join()

Just a little thing to try, so you don't have to use backspace anymore.

Another update!:

I actually found a suppress argument in pynput that would be useful, instead of using backspace again. Here's some code:

from pynput.keyboard import Listener

def onPress(key):
    #replace key 'a' here

with Listener(on_press = onPress, suppress=True) as listener:
    listener.join()

So hopefully this helps, you'll have to figure out typing the key a though. This does, however, stop the user from actually entering any keyboard input while still detecting key presses.