27 votes

Comment puis-je écouter les événements «périphérique USB inséré» sous Linux, en Python?

Je voudrais écrire un script Python pour Amarok sous Linux pour copier automatiquement le podcast stackoverflow sur mon lecteur. Lorsque je branche le lecteur, il monte le lecteur, copie tous les podcasts en attente et éjecte le lecteur. Comment puis-je écouter l'événement "branché"? J'ai regardé à travers hald mais je n'ai pas pu trouver un bon exemple.

39voto

Jaime Soriano Points 3803

Mise à jour: Comme dit dans les commentaires, Hal n'est pas pris en charge dans les distributions récentes, la norme est maintenant udev, Voici un petit exemple qui rend l'utilisation de glib boucle et udev, je garde la couche d'abstraction matérielle version pour des raisons historiques.

C'est fondamentalement l' exemple dans le pyudev documentation, adapté pour travailler avec les anciennes versions, et avec la glib boucle, notez que le filtre doit être personnalisé pour votre besoin:

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

Ancienne version avec Hal et d-bus:

Vous pouvez utiliser D-Bus de liaisons et d'écouter de la DeviceAdded et DeviceRemovedsignaux. Vous aurez à vérifier les capacités de l'appareil Ajouté afin de sélectionner les périphériques de stockage seulement.

Voici un petit exemple, vous pouvez supprimer les commentaires et de les essayer.

import dbus
import gobject

class DeviceAddedListener:
    def __init__(self):

Vous devez vous connecter à Hal Manager en utilisant le Système de 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")

Et vous avez besoin de connecter un écouteur pour les signaux qui vous intéresse sur, dans ce cas - DeviceAdded.

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

Je suis à l'aide d'un filtre basé sur les capacités. Il accepte n'importe quel volume et téléphoner à l' do_something avec des si, vous pouvez lire la documentation Hal pour trouver le plus adapté requêtes pour répondre à vos besoins, ou pour plus d'informations sur les propriétés de la couche d'abstraction matérielle des périphériques.

    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)

Exemple de fonction qui affiche quelques informations sur le 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()

7voto

Chris Jester-Young Points 102876

Je n'ai pas essayé d'écrire un tel programme moi-même, cependant j'ai juste regardé les liens suivants (merci Google!), qui, je pense, sera de vous aider:

En particulier, lire à ce sujet l' org.freedesktop.Hal.Manager interface, et son DeviceAdded et DeviceRemoved événements. :-)

Espérons que cette aide!

4voto

Matt J Points 15475

Je pense que D-Bus de travail de la Chris mentionné, mais si vous êtes à l'aide de KDE4, vous pouvez utiliser le cadre Solide d'une manière similaire à la KDE4 "Nouveau Périphérique Déclarant" applet.

La source C++ pour que l'applet est ici, qui montre comment utiliser Solide pour détecter de nouveaux appareils. Utilisation PyKDE4 pour les liaisons Python pour ces bibliothèques, comme illustré ici.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X