Python evdev检测设备已拔出 [英] Python evdev detect device unplugged

查看:75
本文介绍了Python evdev检测设备已拔出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用出色的evdev"库来监听 USB 条形码阅读器输入,我需要检测设备是否突然被拔掉/无响应,否则读取循环的 python 脚本会在一个单线程慢慢开始吃掉所有可用内存,导致整个系统在一段时间后崩溃.

I'm using the great "evdev" library to listen to a USB barcode reader input and I need to detect if the device suddenly gets unplugged/unresponsive because otherwise the python script reading the loop goes to 100% cpu usage on a single thread and slowly starts to eat all available memory which leads to the entire system crashing after a bit.

我们的想法是检测设备何时拔出并终止当前脚本,导致主管尝试重新启动它,直到设备重新插入/变得响应为止.

The idea is to detect when the device is unplugged and kill the current script leading to supervisor trying to restart it until the device is plugged back in/becomes responsive.

我用来读取输入的代码如下:

The code I'm using to read the input is as follows:

devices = map(InputDevice, list_devices())

keys = {
    2: 1,
    3: 2,
    4: 3,
    5: 4,
    6: 5,
    7: 6,
    8: 7,
    9: 8,
    10: 9,
    11: 0,
}
dev = None
for d in devices:
    if d.name == 'Symbol Technologies, Inc, 2008 Symbol Bar Code Scanner':
        print('%-20s %-32s %s' % (d.fn, d.name, d.phys))
        dev = InputDevice(d.fn)
        break

if dev is not None:
    code = []
    for event in dev.read_loop():
        if event.type == ecodes.EV_KEY:
            if event.value == 00:
                if event.code != 96:
                    try:
                        code.append(keys[event.code])
                    except:
                        code.append('-')
                else:
                    card = "".join(map(str, code))
                    print card

                    code = []
                    card = ""

那么我将如何以正确的方式执行此操作?
我认为这可能可行的一种方法是每 1-5 分钟从 cron 运行第二个脚本,以检查所述设备是否仍然可用,如果现在可用,则从某个文件中获取进程 ID 并以这种方式终止进程,但问题在于这种方法是,如果设备被拔掉,然后在检查之间重新插入,检查器"脚本认为一切正常,而主脚本缓慢崩溃 - 它不会在拔掉"后重新激活

So how would I go about doing this the proper way?
A way I though that might work would be a second script that's run from cron every 1-5 min that checks if said device is still available, if it's now, grab process id from some file and kill the process that way but the problem with this method is that if the device is unplugged and then plugged back between the checks the "checker" script thinks everything is okay while the main script is slowly crashing - it doesn't re-activate after an "unplugging"

推荐答案

python-evdev author这里.知道自己的工作对其他人有用,这种感觉真是太棒了.谢谢你!

python-evdev author here. It is such a great feeling to know that one's work is useful to someone else. Thank you for that!

您绝对应该查看 linux 的设备管理器 - udev.每当添加或删除设备时,Linux 内核都会发出事件.要在 Python 程序中侦听这些事件,您可以使用 pyudev,这是一个很好的、基于 ctypes 的 libudev 绑定(请参阅 监控 部分).

You should definitely look into linux's device manager - udev. The linux kernel emits events whenever a device is added or removed. To listen for these events in a Python program, you can use pyudev, which is an excellent, ctypes based binding to libudev (see the section on monitoring).

下面是一个使用 evdevpyudev 的例子:

Here's an example of using evdev along with pyudev:

import functools
import pyudev

from evdev import InputDevice
from select import select

context = pyudev.Context()
monitor = pyudev.Monitor.from_netlink(context)
monitor.filter_by(subsystem='input')
monitor.start()

fds = {monitor.fileno(): monitor}
finalizers = []

while True:
    r, w, x = select(fds, [], [])

    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 u'py-evdev-uinput' in name:
                    if udev.action == u'add':
                        print('Device added: %s' % udev)
                        fds[dev.fd] = InputDevice(udev.device_node)
                        break
                    if udev.action == u'remove':
                        print('Device removed: %s' % udev)
                        def helper():
                            global fds
                            fds = {monitor.fileno(): monitor}
                        finalizers.append(helper)
                        break

    for fd in r:
        dev = fds[fd]
        for event in dev.read():
            print(event)

    for i in range(len(finalizers)):
        finalizers.pop()()

这篇关于Python evdev检测设备已拔出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆