Python中关于键盘行为的方法总结

最近在倒腾AGV的时候,手动挪小车实在是太重太重了,之前写过控制小车转弯直行的命令,但没有优化,最近小车加了层铠甲实在太重了,于是想写一个类似于小时候玩赛车游戏一样的用手柄或者键盘控制的程序来控制它,中间查阅了相关Python控制键盘的一些第三方库,以及中间遇到的问题做一些整理

1. 前言

我能想到的操控键盘的行为无非有两种,一种是监听键盘的按键,还有一种就是模拟键盘的输入,但我的情景里需要的是前者。

2. pynput库

这个库允许你控制和监视输入设备。 目前,支持鼠标和键盘输入和监视

2.1 控制键盘示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from pynput.keyboard import Key, Controller

keyboard = Controller()

# Press and release space
keyboard.press(Key.space)
keyboard.release(Key.space)

# Type a lower case A; this will work even if no key on the
# physical keyboard is labelled 'A'
keyboard.press('a')
keyboard.release('a')

# Type two upper case As
keyboard.press('A')
keyboard.release('A')
with keyboard.pressed(Key.shift):
keyboard.press('a')
keyboard.release('a')

# Type 'Hello World' using the shortcut type method
keyboard.type('Hello World')

2.2 监听鼠标示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from pynput import keyboard

def on_press(key):
try:
print('alphanumeric key {0} pressed'.format(key.char))
except AttributeError:
print('special key {0} pressed'.format(key))

def on_release(key):
print('{0} 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()

# ...or, in a non-blocking fashion:
listener = mouse.Listener(
on_press=on_press,
on_release=on_release)
listener.start()

我对这个库的第一印象是简洁好用,监听部分的callback函数很优雅,很是喜欢,也简单测试成功了,于是我噗呲噗呲地开始写,然后把代码扔到树莓派上准备run一下,结果悲剧了,报错Xlib.error.DisplayNameError: Bad display name "",网上说通过ssh使用这个库的时候会报错,没法正常监听,具体可以看这个issue,虽然上面有着解决方法,但是我没有得到解决,只能忍痛弃之 (或者可以曲线救国,采用蓝牙键盘?没试过)

3. keyboard库

keyboard库在github上是有较多star的,内容非常多,功能十分强大,你能想到的基本都有….不过我看着头疼,当然,没有选择的另外一个原因是发现了另外一个小脚本来实现我所需要的键盘监听功能,这也是我待会要说的,如果要用其他关于键盘的行为操作,建议好好琢磨下这个库。

4. 神奇小脚本

网上看着看着,突然发现了国外大佬的这篇文章Detecting keyboard input in Python ,完美测试,感觉好极了!先贴代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/usr/bin/python3

# adapted from https://github.com/recantha/EduKit3-RC-Keyboard/blob/master/rc_keyboard.py

import sys, termios, tty, os, time

def getch():
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)

finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch

button_delay = 0.2

while True:
char = getch()

if (char == "p"):
print("Stop!")
exit(0)

if (char == "a"):
print("Left pressed")
time.sleep(button_delay)

elif (char == "d"):
print("Right pressed")
time.sleep(button_delay)

elif (char == "w"):
print("Up pressed")
time.sleep(button_delay)

elif (char == "s"):
print("Down pressed")
time.sleep(button_delay)

elif (char == "1"):
print("Number 1 pressed")
time.sleep(button_delay)

说实话其实getch这个函数我没太看懂,我也不想花时间研究它了,轮子已经造好了,正如这篇文章的作者一样,他也进行了一些搜索并找到了一些示例代码,但是没有一个完全符合要求,直到github上发现了control a robot with a bluetooth keyboard 这篇文章,也是感叹极客的给力!

5. 碎碎念

回过头来整理时发现了更巧的事情,control a robot with a bluetooth keyboard 这篇文章也是用键盘来控制两个马达,控制前进后退(虽然马达类型不一样),真是太巧了,哈哈哈哈哈~