我如何在 python 中创建一个键盘侦听器,它将 return 按下的键的字符?

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

例如,当按下“f”键时,函数将 return 字符“f”,这样我就可以 运行 ord(key) 并获取 ascii 值按下的键。我正在尝试制作一个模拟 Enigma 密码机的程序,并希望在 window 处于焦点时直接从键盘输入,并将密码输出打印到控制台上。 (在一个单独但相关的说明中,我很难记住如何让 print() 函数在输出后省略换行符)。在我看来,pynput 键盘模块就是用于此的工具,但我不太清楚如何使用它。 到目前为止,这是我的完整代码。 “on_press”和“on_release”函数,以及“with Listener(...”之后的所有内容均来自互联网 (https://pythonhosted.org/pynput/keyboard.html),并且,老实说,我不知道它们是做什么的,也不知道如何使用它们。

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):
  print('{0} pressed'.format(key))

def on_release(key):
  print('{0} release'.format(key))
  if key == Key.esc:
    return False

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

with Listener(on_press=on_press, on_release=on_release) as listener:
  listener.join() 

Listeners 的一般精神是他们“倾听”您键盘上可能键入的任何键。

在您上面的代码中(取自网站),当您按下某个键时调用 on_press 函数,这与释放键不同。此功能很有用,因为我们可以尝试存储按下的信息(密钥)供以后使用(用于您的 Enigma 密码机)。

on_release 函数可以被认为是帮助确定监听器是否应该停止监听您的键盘的函数。如果on_release函数returns为False,监听器结束。

为了您的项目,我对上面的代码进行了一些简陋的修改,应该可以帮助您继续听键盘。

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)

从现在开始,您必须将 userInput 合并到您机器的 Enigma 密码方面。我应该提到我对你的代码做了一些小的修改。例如,监听器应该能够理解空格。

如果您有任何后续问题,请告诉我。