如何在 Python 中侦听 Linux 中的“插入 USB 设备”事件?

Posted

技术标签:

【中文标题】如何在 Python 中侦听 Linux 中的“插入 USB 设备”事件?【英文标题】:How can I listen for 'usb device inserted' events in Linux, in Python? 【发布时间】:2010-10-02 22:12:27 【问题描述】:

我想在 Linux 中为 Amarok 编写一个 Python 脚本,以自动将 *** 播客复制到我的播放器。当我插入播放器时,它会挂载驱动器,复制任何待处理的播客,然后弹出播放器。如何收听“插入”事件?我已经浏览了一遍,但找不到一个很好的例子。

【问题讨论】:

哇,您能相信我们过去常常在没有始终连接到互联网的宽带连接的设备上收听播客吗? 【参考方案1】:

更新:正如 cmets 中所说,最近的发行版不支持 Hal,现在的标准是 udev,这是一个利用 glib 循环和 udev的小例子>,出于历史原因,我保留了 Hal 版本。

这基本上是 example in the pyudev documentation,适用于旧版本和 glib 循环,请注意过滤器应根据您的特定需要进行定制:

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

带有 Hal 和 d-bus 的旧版本:

您可以使用 D-Bus 绑定并收听 DeviceAddedDeviceRemoved 信号。 您必须检查已添加设备的功能才能仅选择存储设备。

这里是一个小例子,你可以把cmets去掉试试看。

import dbus
import gobject

class DeviceAddedListener:
    def __init__(self):

您需要使用系统总线连接到 Hal Manager。

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

您需要将侦听器连接到您感兴趣的信号,在本例中为DeviceAdded

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

我正在使用基于功能的过滤器。它将接受任何volume 并调用do_something,如果,您可以阅读 Hal 文档以找到更适合您需求的查询,或有关 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)

显示有关卷的一些信息的示例函数:

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

【讨论】:

我收到此代码错误:dbus.exception.DBusException: org.freedesktop.DBus.Error.ServiceUnknown: 名称 org.freedesktop.Hal 不是由任何 .service 文件提供的。你觉得你能帮我吗? @EtienneLepage-Lepitre Hal 现在已弃用,通常此解决方案将不再起作用:( 添加了使用 udev 的解决方案。【参考方案2】:

我自己没有尝试过编写这样的程序,但是我只是查看了以下两个链接(感谢 Google!),我认为这会有所帮助:

dbus-python tutorial(里面讲了如何使用 Python 访问 D-Bus) HAL 0.5.10 Specification(讨论 HAL 如何将事件发布到 D-Bus)

尤其要了解org.freedesktop.Hal.Manager 接口及其DeviceAddedDeviceRemoved 事件。 :-)

希望这会有所帮助!

【讨论】:

【参考方案3】:

这是一个 5 行的解决方案。

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.

将此保存到文件中,例如 usb_monitor.py,运行 python monitor.py。插入任何 USB,它会打印设备详细信息

→ 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

使用pyudev==0.21.0 在 Python 3.5 上测试。

【讨论】:

【参考方案4】:

我认为 D-Bus 会像 Chris 提到的那样工作,但如果您使用 KDE4,您可能会以类似于 KDE4“新设备通知程序”小程序的方式使用 Solid 框架。

该小程序的 C++ 源代码是 here,它显示了如何使用 Solid 来检测新设备。使用 PyKDE4 将 Python 绑定到这些库,如 here 所示。

【讨论】:

以上是关于如何在 Python 中侦听 Linux 中的“插入 USB 设备”事件?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 Python 脚本侦听和报告服务器 (SSH) 连接?

如何使用 python 宏监视 Libreoffice 文档中的键盘输入?

Python - 如何在应用程序在侦听模式下具有 TCP 端口时即时重新启动应用程序?

Linux下侦听端口被占用,怎么解决?

linux下如何查看硬盘插在主板那个SATA接口上

如何虚拟化 Linux 应用程序正在侦听的 IP 端口?