检测热插拔事件的python脚本
我试图使用python来检测鼠标和键盘事件,并在检测过程中容忍热插拔操作。我编写这个脚本是为了在运行时自动检测键盘和鼠标插件,并输出所有键盘和鼠标事件。我使用evdev和pyudev包来实现这个功能。我的脚本大部分工作正常,包括键盘和鼠标事件检测和插件检测。然而,每当我拔出鼠标时,就会发生许多奇怪的事情,我的脚本无法正常工作。我这里有几个困惑 1当鼠标插入系统时,/dev/input/文件夹中会生成两个文件,包括./mouseX和./eventX。我试图通过cat查看两个源代码的输出,确实存在差异,但我不理解为什么linux会有./mouseX,即使./eventX已经存在 2每当我拔掉鼠标时,./mouseX plug事件首先出现,我在evdev中没有使用该事件,这导致脚本失败,因为我在脚本中读取数据的./eventX被同时拔掉,但我只能在下一轮中检测到./eventX。我在脚本中使用了trickvariable I来绕过这个问题,但即使我可以成功删除鼠标设备,select.select开始无休止的输入读取,即使我没有在键盘上键入任何内容 下面列出的脚本是根据来自的答案修改的,事先感谢您的关注检测热插拔事件的python脚本,python,linux,events,keyboard,Python,Linux,Events,Keyboard,我试图使用python来检测鼠标和键盘事件,并在检测过程中容忍热插拔操作。我编写这个脚本是为了在运行时自动检测键盘和鼠标插件,并输出所有键盘和鼠标事件。我使用evdev和pyudev包来实现这个功能。我的脚本大部分工作正常,包括键盘和鼠标事件检测和插件检测。然而,每当我拔出鼠标时,就会发生许多奇怪的事情,我的脚本无法正常工作。我这里有几个困惑 1当鼠标插入系统时,/dev/input/文件夹中会生成两个文件,包括./mouseX和./eventX。我试图通过cat查看两个源代码的输出,确实存在差
#!/usr/bin/env python
import pyudev
from evdev import InputDevice, list_devices, categorize
from select import select
context = pyudev.Context()
monitor = pyudev.Monitor.from_netlink(context)
monitor.filter_by(subsystem='input')
monitor.start()
devices = map(InputDevice, list_devices())
dev_paths = []
finalizers = []
for dev in devices:
if "keyboard" in dev.name.lower():
dev_paths.append(dev.fn)
elif "mouse" in dev.name.lower():
dev_paths.append(dev.fn)
devices = map(InputDevice, dev_paths)
devices = {dev.fd : dev for dev in devices}
devices[monitor.fileno()] = monitor
count = 1
while True:
r, w, x = select(devices, [], [])
if monitor.fileno() in r:
r.remove(monitor.fileno())
for udev in iter(functools.partial(monitor.poll, 0), None):
# we're only interested in devices that have a device node
# (e.g. /dev/input/eventX)
if not udev.device_node:
break
# find the device we're interested in and add it to fds
for name in (i['NAME'] for i in udev.ancestors if 'NAME' in i):
# I used a virtual input device for this test - you
# should adapt this to your needs
if 'mouse' in name.lower() and 'event' in udev.device_node:
if udev.action == 'add':
print('Device added: %s' % udev)
dev = InputDevice(udev.device_node)
devices[dev.fd] = dev
break
if udev.action == 'remove':
print('Device removed: %s' % udev)
finalizers.append(udev.device_node)
break
for path in finalizers:
for dev in devices.keys():
if dev != monitor.fileno() and devices[dev].fn == path:
print "delete the device from list"
del devices[dev]
for i in r:
if i in devices.keys() and count != 0:
count = -1
for event in devices[i].read():
count = count + 1
print(categorize(event))
mouseX和eventX之间的区别通常是eventX是evdev设备,而mouseX是传统设备,例如,它不支持各种evdev ioctl 我不知道你发布的代码有什么问题,但这里有一个代码片段,它做了正确的事情 !/usr/bin/env python 导入pyudev 导入evdev 导入选择 导入系统 导入功能工具 输入错误号 context=pyudev.context monitor=pyudev.monitor.from_netlinkcontext monitor.filter_by subsystem='input' 注意:在我们最初查询evdev之前,先开始监视,以便 有一个插件,我们在evdev.list_设备之后,我们会选择它 监视器。启动 修改此谓词函数以匹配任何您想要匹配的对象 def predd: 返回d.name.lower中的键盘或d.name.lower中的鼠标 填充活动设备映射,从/dev/input/eventXX映射到 输入设备 设备={} 对于mapevdev.InputDevice中的d,evdev.list_设备: 如果是predd: 打印d 设备[d.fn]=d 专用监控装置 设备['monitor']=监视器 尽管如此: rs,,=select.selectdevices.values,[],[] 无条件ping监视器;如果这是假的话 将不执行操作,因为我们通过了零超时。注意 udev事件需要一些时间才能到达我们这里。 对于iterfunctools.partialmonitor.poll中的udev,0,无: 如果不是udev.device\u节点:中断 如果udev.action==“添加”: 如果udev.device_节点不在设备中: 已添加打印设备:%s%udev 尝试: 设备[udev.device\u节点]=evdev.InputDeviceudev.device\u节点 除IOError外,e: udev报告的设备数量超过了可从 埃夫德夫;一种简单的检查方法是查看devinfo ioctl失败 如果e.errno!=errno.ENOTTY:升起 通过 elif udev.action==“删除”: 注意:这个代码路径不经常使用, 因为select会在读取文件时立即触发读取 描述符消失,而udev事件需要一些时间 是时候向我们宣传了。 如果设备中的udev.device\u节点: 打印设备已删除udev:%s%devices[udev.Device\u节点] 删除设备[udev.device\u节点] 对于rs中的r: 你不能从监视器上读取数据 如果r.fileno==monitor.fileno:继续 如果r.fn不在设备中:继续 Select将立即返回fd进行读取(如果需要) 埃诺德夫。所以一定要处理好。 尝试: 对于r中的事件,请阅读: 通过 打印evdev.categorizeevent 除IOError外,e: 如果e.errno!=errno.ENODEV:升起 已删除打印设备:%s%r del设备[r.fn]