Key Listeners in Python

Key Listeners in python?

It's unfortunately not so easy to do that. If you're trying to make some sort of text user interface, you may want to look into curses. If you want to display things like you normally would in a terminal, but want input like that, then you'll have to work with termios, which unfortunately appears to be poorly documented in Python. Neither of these options are that simple, though, unfortunately. Additionally, they do not work under Windows; if you need them to work under Windows, you'll have to use PDCurses as a replacement for curses or pywin32 rather than termios.


I was able to get this working decently. It prints out the hexadecimal representation of keys you type. As I said in the comments of your question, arrows are tricky; I think you'll agree.

#!/usr/bin/env python
import sys
import termios
import contextlib

@contextlib.contextmanager
def raw_mode(file):
old_attrs = termios.tcgetattr(file.fileno())
new_attrs = old_attrs[:]
new_attrs[3] = new_attrs[3] & ~(termios.ECHO | termios.ICANON)
try:
termios.tcsetattr(file.fileno(), termios.TCSADRAIN, new_attrs)
yield
finally:
termios.tcsetattr(file.fileno(), termios.TCSADRAIN, old_attrs)

def main():
print 'exit with ^C or ^D'
with raw_mode(sys.stdin):
try:
while True:
ch = sys.stdin.read(1)
if not ch or ch == chr(4):
break
print '%02x' % ord(ch),
except (KeyboardInterrupt, EOFError):
pass

if __name__ == '__main__':
main()

How do I create a keyboard listener in python that will return the character of the pressed key?

The general spirit of Listeners is that they "listen" to your keyboard for any keys that you may type.

In your code above (and taken from the website), the on_press function is called when you press down on a certain key, distinct from releasing a key. This function is useful because we can attempt to store the information (the key) that was pressed for later use (for your Enigma cypher machine).

The on_release function can be thought as the function which helps determine if the Listener should stop listening to your keyboard. If the on_release function returns False, the listener ends.

For the purpose of your project, I wrote some janky modification to your code above that should help you move on past listening to the keyboard.

from pynput.keyboard import Key, Listener

wheels = {'fst':[19,-1 , 4 , -2, 11,-3 , 12,-4 , 8 ,-5 , 10,-6 , 9 , 0 , 11,-8 , 8 ,-9 , 5 ,-10, 2 ,-10,-5 ,-13,-10,-13],
'med':[2 , 6 , 10, 5 , 0 , 15, 12,-6 , 13, 2 ,-10, 11,-3 ,-7 , 0 , 8 ,-13,-1 ,-5 ,-9 ,-15, 4 ,-3 ,-8 ,-7 ,-1 ],
'slo':[16, 17, 19, 16,-3 ,-2 , 4 , 17, 6 , 0 ,-8 ,-3 , 13,-9 ,-7 ,-10,-16,-6 ,-5 ,-4 , 3 ,-4 ,-2 ,-1 ,-18,-13],
'rfl':[8 , 22, 18, 4 , 1 ,-1 , 19,-4 ,-8 , 5 , 2 , 8 ,-2 , 3 ,-5 , 7 ,-3 , 1 ,-1 ,-8 ,-18, 3 ,-7 ,-22,-3 ,-19]}
dials = [0, 0, 0, 0]

def incr():
dials[0] = (dials[0] + 1) % 26
if(dials[0]==0):
dials[1] = (dials[1] + 1) % 26
if(dials[1]==0):
dials[2] = (dials[2] + 1) % 26

def shift(char,level):
return(chr(ord(char) - 97 + wheels[level][(ord(char) - 97 + dials[level]) % 26]))

def on_press(key):
# Use global variable input in order to keep track of current word.
global userInput
try:
userInput += key.char
except AttributeError:
#print('special key {0} pressed'.format(key))
if key == Key.space:
userInput += ' '

def on_release(key):
if key == Key.enter:
return False
elif key == Key.esc:
return False

def route(char):
#process the character through each level of scrambling
incr()

# esc to escape listener.
userInput = ""
with Listener(on_press=on_press, on_release=on_release) as listener:
listener.join()
print('userInput', userInput)

From this point on, you would have to incorporate the userInput into your the Enigma cypher aspect of your machine. I should mention that I made minor modifications to your code. For instance, the Listener should be able to understand spaces.

If you have any follow up questions, please let me know.

Are there any Key listeners in python (v 2.7)

You can try the following code. It does not contain 3rd party module.

Code:

import sys, tty, os, termios

def getkey():
old_settings = termios.tcgetattr(sys.stdin)
tty.setcbreak(sys.stdin.fileno())
try:
while True:
b = os.read(sys.stdin.fileno(), 3).decode()
if len(b) == 3:
k = ord(b[2])
else:
k = ord(b)
key_mapping = {
127: 'backspace',
10: 'return',
32: 'space',
9: 'tab',
27: 'esc',
65: 'up',
66: 'down',
67: 'right',
68: 'left'
}
return key_mapping.get(k, chr(k))
finally:
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings)

try:
while True:
k = getkey()
print("Detected key: {}".format(k))
if k == 'esc':
quit()
else:
print(k)
except (KeyboardInterrupt, SystemExit):
os.system('stty sane')
print('stopping.')

Test and output:

>>> python3 test.py 
Detected key: a
a
Detected key: s
s
Detected key: d
d
Detected key: f
f
Detected key: right
right
Detected key: left
left
Detected key: space
space
Detected key: tab
tab
stopping.

Note: If you are able to use an external Python module, I suggest a the pynput or keyboard Python module. Links: https://github.com/boppreh/keyboard , https://github.com/moses-palmer/pynput

Stopping a python program when an arbitrary key was pressed while the program is running

After carefully understanding about the threads and pynput module, I managed to stop a for loop (or any program which runs as a separate thread) using a key press callback.

from pynput import keyboard
import os
import threading
import time

loop_running = False

def on_press(key):
print(dir(key))
global loop_running
#if key == keyboard.Key.delete and not loop_running:
if ('char' in dir(key)) and (key.char == 's') and (not loop_running):
t=threading.Thread(target=start_loop)
t.start()

#elif key==keyboard.Key.tab: #if this is used, the attributes related to 'key' will be changed. you can see them since I have used a print(dir(key))
elif key.char == 'q':
loop_running=False


def start_loop():
global loop_running
loop_running = True
for i in range(100):
if not loop_running:
os._exit(0)

print(i)
time.sleep(1)

with keyboard.Listener(on_press=on_press) as listner:
listner.join()

Listening to specific keys with pynput.Listener and keylogger?

You can import Key module from pynput.keyboard and check for the type of key-strokes.

#in pynput, import keyboard Listener method
from pynput.keyboard import Listener, Key

#set log file location
logFile = "/home/diego/log.txt"

def writeLog(key):
'''
This function will be responsible for receiving the key pressed.
via Listener and write to log file
'''

if(key == Key.left or key == Key.up):
#convert the keystroke to string
keydata = str(key)

#open log file in append mode
with open(logFile, "a") as f:
f.write(keydata)

#open the Keyboard Listener and listen for the on_press event
#when the on_press event occurs call the writeLog function

with Listener(on_press=writeLog) as l:
l.join()


Related Topics



Leave a reply



Submit