How to Detect Key Presses In Python
This demonstration shows you how to detect key presses using the pynput module. These can then be logged to a file as no console is displayed. This is very similar to a key logger.
If you haven’t used or setup pip before, go to my tutorial at how-to-setup-pythons-pip to setup pip.
We will be using the pynput module to listen to keyboard events. To install this module execute pip install pynput in cmd. Watch the output to make sure no errors have occurred; it will tell you when the module has been successfully installed.
To double-check that it was installed successfully, open up IDLE and execute the command import pynput ; no errors should occur.
Create a new python file and save it with a .py file extension. You will first want to import Listener from pynput.keyboard.
from pynput.keyboard import Listener
Setup the listener by creating an instance in a with statement and using it’s .join() method to join it to the main thread.
with Listener() as listener: listener.join()
Create three methods; on_press and on_release with the parameters as shown below.
def on_press(key): pass def on_release(key): pass
Link these methods to the listener instance with the function names as the args; I have named the methods as they are defined in the listener class. Now when an action occurs, one of these methods will be run.
with Listener(on_press=on_press, on_release=on_release) as listener:
To make sure these are running, add some print statements to each method. Save and run the script. Press a few keys, you should see output like below.
def on_press(key): print("Key pressed") def on_release(key): print("Key released")
Using these print statements and the parameters provided, we can give more information when printing. Run this again to make sure it is working properly (example output below).
def on_press(key): print("Key pressed: ".format(key)) def on_release(key): print("Key released: ".format(key))
If you want this script to be run in the background. Click File -> Save As and save it with a .pyw file extension. Now when it is run outside IDLE there will be no console window and it will not look like it is running. But to make sure the console doesn’t appear, we need to first remove the print statements.
Import logging and set up the basic configuration as I have below. After that, change all print statements to logging.info.
logging.basicConfig(filename="key_log.txt", level=logging.DEBUG, format='%(asctime)s: %(message)s')
def on_press(key): logging.info("Key pressed: ".format(key)) def on_release(key): logging.info("Key released: ".format(key))
Now when the script is run, nothing should be printed to the console. This is because it is all being saved to the file declared in the basic configuration.
Save and close IDLE. Open the file named key_log.txt next to your python script; all the events should be logged in here. For example, here is one of my logs typing Wow! :
2020-04-07 22:52:58,233: Key pressed: Key.shift 2020-04-07 22:52:58,514: Key pressed: 'W' 2020-04-07 22:52:58,649: Key released: Key.shift 2020-04-07 22:52:58,649: Key released: 'w' 2020-04-07 22:52:58,942: Key pressed: 'o' 2020-04-07 22:52:59,058: Key released: 'o' 2020-04-07 22:52:59,205: Key pressed: 'w' 2020-04-07 22:52:59,318: Key released: 'w' 2020-04-07 22:52:59,430: Key pressed: Key.shift 2020-04-07 22:52:59,590: Key pressed: '!' 2020-04-07 22:52:59,710: Key released: '!' 2020-04-07 22:52:59,853: Key released: Key.shift
The actual location of this file will be in the current working directory of where you run the script from
Just as a quick note, the Listener class is a thread which means as soon as it has joined to the main thread no code will be executed after the .join() until the Listener is stopped.
As stated here in the pynput docs on readthedocs.io, we can call pynput.keyboard.Listener.stop anywhere in the script to stop the thread or return False from a callback to stop the listener. As shown in my video, we can also just call listener.stop() in one of the definitions due to the fact that that the listener is now in scope and is an instance os Listener.
from pynput.keyboard import Listener import logging # Setup logging logging.basicConfig(filename="key_log.txt", level=logging.DEBUG, format='%(asctime)s: %(message)s') def on_press(key): # The function that's called when a key is pressed logging.info("Key pressed: ".format(key)) def on_release(key): # The function that's called when a key is released logging.info("Key released: ".format(key)) with Listener(on_press=on_press, on_release=on_release) as listener: # Create an instance of Listener listener.join() # Join the listener thread to the main thread to keep waiting for keys
Making Things a Bit More Readable
Everything being on a new line with both key presses and releases can be very helpful for identifying sequences but can be a bit hard to read. Here is a modified script that can put everything on one line and enters when enter is pressed.
from pynput.keyboard import Listener, Key filename = "key_log.txt" # The file to write characters to def on_press(key): f = open(filename, 'a') # Open the file if hasattr(key, 'char'): # Write the character pressed if available f.write(key.char) elif key == Key.space: # If space was pressed, write a space f.write(' ') elif key == Key.enter: # If enter was pressed, write a new line f.write('\n') elif key == Key.tab: # If tab was pressed, write a tab f.write('\t') else: # If anything else was pressed, write [] f.write('[' + key.name + ']') f.close() # Close the file with Listener(on_press=on_press) as listener: # Setup the listener listener.join() # Join the thread to the main thread
Here is a sample of some of the output:
[shift]I am typing this in notepad [shift]Here is a new line [shift]Opps, [shift]I spelt that wro[backspace][backspace]ro[backspace][backspace]ord incorrectly [shift]Here as [backspace][backspace]re some special keys[shift]:[shift][ctrl_l][alt_l][alt_r][ctrl_r][shift_r]
Common Issues and Questions
ModuleNotFoundError/ImportError: No module named ‘pynput’
Did you install pynput? This error will not occur if you installed it properly. If you have multiple versions of Python, make sure you are installing pynput on the same version as what you are running the script with.
Owner of PyTutorials and creator of auto-py-to-exe. I enjoy making quick tutorials for people new to particular topics in Python and tools that help fix small things.
Detect Keypress in Python
- Detect KeyPress Using the keyboard Module in Python
- Detect KeyPress Using the pynput Module in Python
If you need access to the hardware like input devices such as the keyboard, there are modules available in Python which can make your lives much easier. Using such modules, you can easily perform the task you want without dealing with the complexities of the system.
In this article, you will learn how to detect keypress using modules in Python. There are many modules used to detect keypress in Python, and out of which, the two most popular and widely used modules are keyboard and pynput .
Detect KeyPress Using the keyboard Module in Python
The keyboard module allows us to take full control of the keyboard and comes with various predefined methods to choose from. These methods make it much easier for us to work with the keyboard and detect the user’s physical keypresses on the keyboard.
To install the keyboard module, execute the below command inside your command prompt or terminal.
First, you have to import the keyboard module into the program. Here, we are using three methods to detect keypress in Python read_key() , is_pressed() and on_press_key() .
import keyboard while True: if keyboard.read_key() == "p": print("You pressed p") break while True: if keyboard.is_pressed("q"): print("You pressed q") break keyboard.on_press_key("r", lambda _:print("You pressed r"))
You pressed p You pressed q You pressed r
The read_key() will read which key a user has pressed on the keyboard, and if it’s that key which you wanted, in this case, p , it will print the message You pressed p . The read_key() function returns a character.
The is_pressed() takes a character as an input, and if it matches with the key which the user has pressed, it will return True and False otherwise.
The on_press_key() takes two parameters as an input, the first is the character, and the second is the function. If the user presses the key that matches the key specified as the first parameter of the on_press_key() function, it will only execute the function you have passed in as the second parameter.
Detect KeyPress Using the pynput Module in Python
The pynput module is used to detect and control input devices, mainly mouse and keyboard. But in this tutorial, you will only see how to use this module for detecting keypress on the keyboard. Before using this module, you first have to install it using the command below.
To use this module for detecting keypress, you first have to import keyboard from pynput module.
from pynput import keyboard def on_press(key): try: print('Alphanumeric key pressed: '.format( key.char)) except AttributeError: print('special key pressed: '.format( key)) def on_release(key): print('Key released: '.format( key)) if key == keyboard.Key.esc: # Stop listener return False # Collect events until released with keyboard.Listener( on_press=on_press, on_release=on_release) as listener: listener.join()
Alphanumeric key pressed: a Key released: 'a' Alphanumeric key pressed: b Key released: 'b' special key pressed: Key.ctrl_l Key released: Key.ctrl_l
Note that the above output may vary depending upon which keys are pressed by the user.
To detect keypress, we are defining two functions, on_press and on_release . The function on_press will be executed when the user will press a button on the keyboard, and as soon as the user releases that button, the on_release function will be executed.
Both functions are only printing the keys pressed and released by the user to the console window. You can change the implementation of these two functions based on your requirements.
Then at the end, we have a Listener that will listen to the keyboard events, and it will execute the on_press and on_release functions accordingly.
Sahil is a full-stack developer who loves to build software. He likes to share his knowledge by writing technical articles and helping clients by working with them as freelance software engineer and technical writer on Upwork.