Im trying to make a very simple program that presses the F5 key when I press another key (example q). Whenever I use regular characters a-z I compare using
if key.char == 'q':
This works fine until I introduce Key.f5 (or any other Key.)
if key.char == 'q':
keyboard.press(Key.f5)
keyboard.release(Key.f5)
I then get this error:
if f(*args) is False:
File "C:\Users\lkl\Desktop\combination-1.py", line 17, in on_release
if key.char == 'q':
AttributeError: 'Key' object has no attribute 'char'
I have tried renaming key to key1 and other names. I have tried to create a controller called keyboard1 and other names. I have tried to isolate the following code in its own function:
keyboard.press(Key.f5)
keyboard.release(Key.f5)
I have tried to catch the error with Try Except statements. The Error still comes. And it ends the execution.
I have tried avoid to key.char by simply comparing key with the Unicode and html code for the character. This triggers no action when pressing q
if key == 'U+0071':
The thing is, the program executes the F5command even when I use key.char but the AttributeError stops the program.
I am able to make this run:
if key == Key.shift_l:
keyboard.press(Key.f5)
keyboard.release(Key.f5)
but I need the key to be a simple a-z key, because the machine is receiving the key through a keylogger on a seperate machine. And it can only send/receive non-special keys. eg. numbers and letters.
This is completely wrinkling my brain. I can't find a single way to send F5 while listening for 'q'.
Here is the full code:
from pynput.mouse import Listener as ms
from pynput.keyboard import Listener as kb
from pynput.keyboard import Key, Controller
import os
import sys
import subprocess
keyboard = Controller()
def on_press(key):
print('{0} pressed'.format(
key))
def on_release(key):
print('{0} release'.format(
key))
if key.char == 'q':
keyboard.press(Key.f5)
keyboard.release(Key.f5)
if key == "a":
subprocess.call("C:/Users/lkl/Desktop/fastsafelargetest - Copy.vbs", shell=True)
if key == 'z':
subprocess.call("C:/Users/lkl/Desktop/autofill.vbs", shell=True)
if key == Key.esc:
return False
def on_click(x, y, button, pressed):
if pressed:
pass
else:
#subprocess.call("C:/Users/lkl/Desktop/fastsafelargetest - Copy.vbs", shell=True)
print('Released')
def on_scroll(x, y, dx, dy):
print('Scrolled {0}'.format(
(x, y)))
# Collect events until released
with ms(
on_click=on_click,
on_scroll=on_scroll) as listener:
with kb(
on_press=on_press,
on_release=on_release) as listener:
listener.join()
Based on @jim-todd answer i found the python module "keyboard". Its not a very elegant solution but it technically provides a workaround for the problem. I use this line to check for key input:
keyboard.is_pressed('q'):
rename my pynput controller to keyboard1
keyboard1 = Controller()
And the entire code for this problem can look like this (not all imports here are necessary).
from pynput.mouse import Listener as ms
from pynput.keyboard import Listener as kb
from pynput.keyboard import Key, Controller
import keyboard
import os
import sys
import subprocess
import time
keyboard1 = Controller()
def on_press(key):
while keyboard.is_pressed('q'):
keyboard1.press(Key.f5)
keyboard1.release(Key.f5)
print('{0} pressed'.format(
key))
time.sleep(0.05)
break
if key == Key.esc:
return False
with ms() as listener:
with kb(
on_press=on_press) as listener:
listener.join()
You're going to have to test whether the key object has a char before using it.
One way to do that which I used in my application with pynput would be to do something like this (adapted from your code)
def on_release(key):
print('{0} release'.format(key))
if hasattr(key, 'char'):
if key.char == 'q':
keyboard.press(Key.f5)
keyboard.release(Key.f5)
if key == "a":
subprocess.call("C:/Users/lkl/Desktop/fastsafelargetest - Copy.vbs", shell=True)
if key == 'z':
subprocess.call("C:/Users/lkl/Desktop/autofill.vbs", shell=True)
if key == Key.esc:
return False
Note how all keys that use char codes are inside of this part
if hasattr(key, 'char'):
That will avoid the error :)
btw, on pynput's documentation they do it a different way, by doing a try-catch on the AttributeError, but I try to avoid those especially for performance-critical things like checking the keyboard every frame in a game.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With