2009-01-22 14 views
34

Me gustaría escribir un script de Python para Amarok en Linux para copiar automáticamente el podcast de stackoverflow a mi reproductor. Cuando enchufo el reproductor, montaría la unidad, copiaría cualquier podcast pendiente y expulsaría el reproductor. ¿Cómo puedo escuchar el evento "enchufado"? Miré a través de hald pero no pude encontrar un buen ejemplo.¿Cómo puedo escuchar los eventos 'usb device inserted' en Linux, en Python?

Respuesta

50

actualización: Como se ha dicho en los comentarios, Hal no se admite en las distribuciones recientes, el estándar actual es udev, He aquí un pequeño ejemplo que hace uso del bucle de simplista y udev, me quedo con la versión de Hal por razones históricas razones.

Esta es básicamente la example in the pyudev documentation, adaptado para trabajar con las versiones anteriores, y con el bucle simplista, observe que el filtro debe ser personalizado para su específica necesidad:

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

versión antigua con Hal y d parada de microbus:

puede utilizar los enlaces de D-Bus y escuchar DeviceAdded y DeviceRemoved señales. Deberá verificar las capacidades del dispositivo Agregado para seleccionar únicamente los dispositivos de almacenamiento.

Aquí hay un pequeño ejemplo, puede eliminar los comentarios y probarlo.

import dbus 
import gobject 

class DeviceAddedListener: 
    def __init__(self): 

Debe conectarse a Hal Manager utilizando el Bus del sistema.

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

y hay que conectar un oyente a las señales de que está interesado en, en este caso DeviceAdded.

 self.hal_manager.connect_to_signal("DeviceAdded", self._filter) 

Estoy usando un filtro basado en capacidades.Aceptará cualquier volume y llamará al do_something con if, puede leer la documentación de Hal para encontrar las consultas más adecuadas para sus necesidades o más información sobre las propiedades de los dispositivos de Hal.

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) 

función Ejemplo que muestra cierta información sobre el volumen:

 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() 
+1

Recibo un error con este código: dbus.exception.DBusException: org.freedesktop.DBus.Error.ServiceUnknown: El nombre org.freedesktop.Hal no fue proporcionada por los archivos .Service. ¿Crees que podrías ayudarme? –

+0

@ EtienneLepage-Lepitre Hal está en desuso ahora, en general, esta solución ya no funcionará :( – Andy

+1

Solución agregada usando udev. –

7

No he intentado escribir un programa de este tipo a mí mismo, sin embargo he miraba a los siguientes dos enlaces (gracias Google!), Que creo que va a ser de ayuda:

En particular, leer sobre la interfaz org.freedesktop.Hal.Manager, y su DeviceAdded y DeviceRemoved eventos. :-)

Espero que esto ayude!

4

Creo que D-Bus funcionaría como mencionó Chris, pero si usa KDE4, puede usar Solid Framework de forma similar al applet KDE4 "New Device Notifier".

La fuente de C++ para ese applet es here, que muestra cómo usar Solid para detectar nuevos dispositivos. Utilice PyKDE4 para enlaces de Python a estas bibliotecas, como se muestra en here.

2

Aquí es una solución en 5 líneas.

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. 

Guardar este archivo a un usb_monitor.py decir, ejecutar python monitor.py. Conecte cualquier puerto USB e imprimirá los detalles del dispositivo

→ 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 

Probado en Python 3.5 con pyudev==0.21.0.

Cuestiones relacionadas