Python evdev detect device unplugged

2024/9/20 19:23:05

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)breakif 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 cardcode = []card = ""

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"

Answer

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!

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).

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

import functools
import pyudevfrom evdev import InputDevice
from select import selectcontext = 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 fdsfor 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 needsif u'py-evdev-uinput' in name:if udev.action == u'add':print('Device added: %s' % udev)fds[dev.fd] = InputDevice(udev.device_node)breakif udev.action == u'remove':print('Device removed: %s' % udev)def helper():global fdsfds = {monitor.fileno(): monitor}finalizers.append(helper)breakfor fd in r:dev = fds[fd]for event in dev.read():print(event)for i in range(len(finalizers)):finalizers.pop()()
https://en.xdnf.cn/q/72443.html

Related Q&A

python: urllib2 using different network interface

I have the following code:f = urllib2.urlopen(url) data = f.read() f.close()Its running on a machine with two network interfaces. Id like to specify which interface I want the code to use. Specifically…

RuntimeError: as_numpy_iterator() is not supported while tracing functions

while i was using function as_numpy_iterator() got error--------------------------------------------------------------------------- RuntimeError Traceback (most recent call…

Pandas assert_frame_equal error

Im building test cases and I want to compare 2 dataframes. Even though dataframe have the same columns and values assert_frame_equal reports are not equal. Column order is different, I tried reordering…

Multiple lines on line plot/time series with matplotlib

How do I plot multiple traces represented by a categorical variable on matplotlib or plot.ly on Python? I am trying to replicate the geom_line(aes(x=Date,y=Value,color=Group) function from R.Is there …

Python ABCs: registering vs. subclassing

(I am using python 2.7) The python documentation indicates that you can pass a mapping to the dict builtin and it will copy that mapping into the new dict:http://docs.python.org/library/stdtypes.html#…

python - ensure script is activated only once

Im writing a Python 2.7 script. In summary, this script is being run every night on Linux and activates several processes.Id like to ensure this script is not run multiple times in parallel (basically …

How to set up auto-deploy to AppEngine when pushing to Git Repository

Ive heard that other platforms support auto-deployment of their code to production when they push changes to their Git repository.Can I set up something similar to this for AppEngine? How?Im using Py…

#include zbar.h 1 error generated when running pip install zbar

Im trying to run pip install zbar and for some reason I cant seem to find an answer to solve this dependency issue. Any help would be extremely appreciated. See traceback below:Downloading/unpacking zb…

Django model field default based on another model field

I use Django Admin to build a management site. There are two tables, one is ModelA with data in it, another is ModelB with nothing in it. If one model field b_b in ModelB is None, it can be displayed o…

How do I improve remove duplicate algorithm?

My interview question was that I need to return the length of an array that removed duplicates but we can leave at most 2 duplicates. For example, [1, 1, 1, 2, 2, 3] the new array would be [1, 1, 2, 2,…