How can I listen for 'usb device inserted' events in Linux, in Python?
Update: As said in comments, Hal is not supported in recent distributions, the standard now is udev, Here is a small example that makes use of glib loop and udev, I keep the Hal version for historical reasons.
This is basically the example in the pyudev documentation, adapted to work with older versions, and with the glib loop, notice that the filter should be customized for your specific needing:
import glib
from pyudev import Context, Monitor
try:
from pyudev.glib import MonitorObserver
def device_event(observer, device):
print 'event {0} on device {1}'.format(device.action, device)
except:
from pyudev.glib import GUDevMonitorObserver as MonitorObserver
def device_event(observer, action, device):
print 'event {0} on device {1}'.format(action, device)
context = Context()
monitor = Monitor.from_netlink(context)
monitor.filter_by(subsystem='usb')
observer = MonitorObserver(monitor)
observer.connect('device-event', device_event)
monitor.start()
glib.MainLoop().run()
Old version with Hal and d-bus:
You can use D-Bus bindings and listen to DeviceAdded
and DeviceRemoved
signals.
You will have to check the capabilities of the Added device in order to select the storage devices only.
Here is a small example, you can remove the comments and try it.
import dbus
import gobject
class DeviceAddedListener:
def __init__(self):
You need to connect to Hal Manager using the System Bus.
self.bus = dbus.SystemBus()
self.hal_manager_obj = self.bus.get_object(
"org.freedesktop.Hal",
"/org/freedesktop/Hal/Manager")
self.hal_manager = dbus.Interface(self.hal_manager_obj,
"org.freedesktop.Hal.Manager")
And you need to connect a listener to the signals you are interested on, in this case DeviceAdded
.
self.hal_manager.connect_to_signal("DeviceAdded", self._filter)
I'm using a filter based on capabilities. It will accept any volume
and will call do_something
with if, you can read Hal documentation to find the more suitable queries for your needs, or more information about the properties of the Hal devices.
def _filter(self, udi):
device_obj = self.bus.get_object ("org.freedesktop.Hal", udi)
device = dbus.Interface(device_obj, "org.freedesktop.Hal.Device")
if device.QueryCapability("volume"):
return self.do_something(device)
Example function that shows some information about the volume:
def do_something(self, volume):
device_file = volume.GetProperty("block.device")
label = volume.GetProperty("volume.label")
fstype = volume.GetProperty("volume.fstype")
mounted = volume.GetProperty("volume.is_mounted")
mount_point = volume.GetProperty("volume.mount_point")
try:
size = volume.GetProperty("volume.size")
except:
size = 0
print "New storage device detectec:"
print " device_file: %s" % device_file
print " label: %s" % label
print " fstype: %s" % fstype
if mounted:
print " mount_point: %s" % mount_point
else:
print " not mounted"
print " size: %s (%.2fGB)" % (size, float(size) / 1024**3)
if __name__ == '__main__':
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
loop = gobject.MainLoop()
DeviceAddedListener()
loop.run()
I haven't tried writing such a program myself, however I've just looked at the following two links (thanks Google!), which I think will be of help:
- dbus-python tutorial (which talks about how to use Python to access D-Bus)
- HAL 0.5.10 Specification (which talks about how HAL publishes events to D-Bus)
In particular, read about the org.freedesktop.Hal.Manager
interface, and its DeviceAdded
and DeviceRemoved
events. :-)
Hope this helps!
Here is a solution in 5 lines.
import pyudev
context = pyudev.Context()
monitor = pyudev.Monitor.from_netlink(context)
monitor.filter_by(subsystem='usb')
for device in iter(monitor.poll, None):
if device.action == 'add':
print('{} connected'.format(device))
# do something very interesting here.
Save this to a file say usb_monitor.py
, run python monitor.py
. Plug any usb and it will print device details
→ python usb_monitor.py
Device('/sys/devices/pci0000:00/0000:00:14.0/usb1/1-6/1-6:1.0') connected
Device('/sys/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0') connected
Tested on Python 3.5 with pyudev==0.21.0
.