Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I listen for 'usb device inserted' events in Linux, in Python?

Tags:

python

linux

usb

I'd like to write a Python script for Amarok in Linux to automatically copy the stackoverflow podcast to my player. When I plug in the player, it would mount the drive, copy any pending podcasts, and eject the player. How can I listen for the "plugged in" event? I have looked through hald but couldn't find a good example.

like image 447
joeforker Avatar asked Jan 22 '09 14:01

joeforker


People also ask

How do I access USB devices on Linux?

Double-click the folder on your desktop that says Username's Home, where Username is your username. Then in the field next to Location, type /mnt/usb , or the appropriate directory you want to access.

How do I run a Python program from a USB?

You need to pass a script to it, so it may be more something like d:\python.exe d:\path\to\some\script.py from a command line. But it would also be surprising if python is not already installed on your system. You also don't necessarily need the python.exe on your usb disk to run the .


2 Answers

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() 
like image 125
Jaime Soriano Avatar answered Sep 23 '22 04:09

Jaime Soriano


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!

like image 35
Chris Jester-Young Avatar answered Sep 20 '22 04:09

Chris Jester-Young