0

我正在编写一个小程序来列出可用的 USB 设备。我创建了一个带有函数的单独文件,以便可以随时从其他脚本访问它。此函数的主要目标是返回列表/数组作为输出。如果我使用 print 命令,它会成功打印可用设备的列表。但是,当我使用 return 命令时,它只会重新启动第一个检测到的设备。我已经从 SO 解决了其他类似的问题,但找不到任何有效的解决方案。这是我尝试使用 dbus 的代码。任何帮助都会得到帮助。

#!/usr/bin/python2.7
import dbus

def find_usb(self):
    bus = dbus.SystemBus()
    ud_manager_obj = bus.get_object("org.freedesktop.UDisks", "/org/freedesktop/UDisks")
    ud_manager = dbus.Interface(ud_manager_obj, 'org.freedesktop.UDisks')

    for dev in ud_manager.EnumerateDevices():
        device_obj = bus.get_object("org.freedesktop.UDisks", dev)
        device_props = dbus.Interface(device_obj, dbus.PROPERTIES_IFACE)
        if device_props.Get('org.freedesktop.UDisks.Device', "DriveConnectionInterface") == "usb" and device_props.Get('org.freedesktop.UDisks.Device', "DeviceIsPartition"):
            if device_props.Get('org.freedesktop.UDisks.Device', "DeviceIsMounted"):
                device_file = device_props.Get('org.freedesktop.UDisks.Device', "DeviceFile")
                #print device_file
                return device_file

            else:
                print "Device not mounted"
find_usb("")
4

3 回答 3

4

您将返回您匹配的第一个设备。而是构建一个列表并返回该列表:

def find_usb(self):
    bus = dbus.SystemBus()
    ud_manager_obj = bus.get_object("org.freedesktop.UDisks", "/org/freedesktop/UDisks")
    ud_manager = dbus.Interface(ud_manager_obj, 'org.freedesktop.UDisks')

    found = []

    for dev in ud_manager.EnumerateDevices():
        device_obj = bus.get_object("org.freedesktop.UDisks", dev)
        device_props = dbus.Interface(device_obj, dbus.PROPERTIES_IFACE)
        if device_props.Get('org.freedesktop.UDisks.Device', "DriveConnectionInterface") == "usb" and device_props.Get('org.freedesktop.UDisks.Device', "DeviceIsPartition"):
            if device_props.Get('org.freedesktop.UDisks.Device', "DeviceIsMounted"):
                device_file = device_props.Get('org.freedesktop.UDisks.Device', "DeviceFile")
                #print device_file
                found.append(device_file)

            else:
                print "Device not mounted"

    return found

一条return语句立即结束函数;通过将 areturn放入循环中,您将在该点退出函数并过早结束循环。

另一种方法是通过使用语句生成匹配项,使其成为生成器函数;然后,您可以只循环一次的结果,但您将按需生成设备文件:yieldself.find_usb()

def find_usb(self):
    bus = dbus.SystemBus()
    ud_manager_obj = bus.get_object("org.freedesktop.UDisks", "/org/freedesktop/UDisks")
    ud_manager = dbus.Interface(ud_manager_obj, 'org.freedesktop.UDisks')

    for dev in ud_manager.EnumerateDevices():
        device_obj = bus.get_object("org.freedesktop.UDisks", dev)
        device_props = dbus.Interface(device_obj, dbus.PROPERTIES_IFACE)
        if device_props.Get('org.freedesktop.UDisks.Device', "DriveConnectionInterface") == "usb" and device_props.Get('org.freedesktop.UDisks.Device', "DeviceIsPartition"):
            if device_props.Get('org.freedesktop.UDisks.Device', "DeviceIsMounted"):
                device_file = device_props.Get('org.freedesktop.UDisks.Device', "DeviceFile")
                #print device_file
                yield device_file

            else:
                print "Device not mounted"

    return found

然而,生成器是一种更先进的技术。

于 2013-09-11T17:31:18.613 回答
1

您应该创建一个列表变量并将设备附加到它。然后在函数结束时,返回列表。

#!/usr/bin/python2.7
import dbus

def find_usb(self):
    devices = [] # instantiate empty list variable!
    bus = dbus.SystemBus()
    ud_manager_obj = bus.get_object("org.freedesktop.UDisks", "/org/freedesktop/UDisks")
    ud_manager = dbus.Interface(ud_manager_obj, 'org.freedesktop.UDisks')

    for dev in ud_manager.EnumerateDevices():
        device_obj = bus.get_object("org.freedesktop.UDisks", dev)
        device_props = dbus.Interface(device_obj, dbus.PROPERTIES_IFACE)
        if device_props.Get('org.freedesktop.UDisks.Device', "DriveConnectionInterface") == "usb" and device_props.Get('org.freedesktop.UDisks.Device', "DeviceIsPartition"):
            if device_props.Get('org.freedesktop.UDisks.Device', "DeviceIsMounted"):
                device_file = device_props.Get('org.freedesktop.UDisks.Device', "DeviceFile")
                #print device_file
                devices.append(device_file)

            else:
                print "Device not mounted"
    return devices

find_usb("")
于 2013-09-11T17:32:56.117 回答
0

甚至理解你的代码的一个大问题是逻辑结构隐藏在很多缩进中。这是一个重写,它保留了原始操作,同时允许看到结构。

#!/usr/bin/python2.7
import dbus

def find_usb(self):
    ofud = 'org.freedesktop.UDisks' # convenience string for brevity
    bus = dbus.SystemBus()

    ud_manager_obj = bus.get_object(ofud, "/org/freedesktop/UDisks")
    ud_manager = dbus.Interface(ud_manager_obj, ofud)

    for dev in ud_manager.EnumerateDevices():
        device_obj = bus.get_object(ofud, dev)
        device_props = dbus.Interface(device_obj, dbus.PROPERTIES_IFACE)
        dp_get = device.props.Get   # convenience method for brevity
        if (dp_get(ofud, "DriveConnectionInterface") == "usb" and
            dp_get(ofud, "DeviceIsPartition")):
            if dp_get(ofud, "DeviceIsMounted"):
                device_file = dp_get(ofud + '.Device', "DeviceFile")
                print device_file
                return device_file
            else:
                print "Device not mounted"
                return None         # implied
         else:
             return None            # implied
    return None

find_usb("")

其他人已经充分回答了问题所在,但阅读困难无济于事。部分原因不是你的错,dbus 接口很冗长,但是你可以像我对ofudand所做的那样来驯服它dp_get

Python和PEP-20的PEP-8 样式指南 Python的 Zen在很大程度上是为了帮助您编写使错误更容易看到的代码。特别是,你的条件的深层嵌套可以清理很多:

if dp_get(ofud, 'DriveConnectionInterface') != 'usb':
    continue
if dp_get(ofud, 'DeviceIsPartition') and dp_get(oufd, 'DeviceIsMounted'):
     device_file = dp_get(oufd + '.Device', "DeviceFile")
     found.append(device_file)

由于您的原始代码对非 USB 设备没有任何作用,因此“快速失败”到循环的下一次迭代并跳过整个缩进级别会更清楚。当然还有其他方法可以使代码的意图更加明显,我只是展示了一些。

可读性很重要。

于 2013-09-11T18:53:54.587 回答