Python中查询连接的USB设备信息的简单方法?

47 投票
7 回答
205966 浏览
提问于 2025-04-17 06:12

我想知道怎么用Python查询连接的USB设备信息。我想获取设备的UID和设备名称(比如:SonyEricsson W660),还有设备的路径(比如:/dev/ttyACM0)。

另外,从这些信息中,哪个参数最适合用来识别设备,以便下次连接时能再次找到它?是UID吗?

我现在在使用Ubuntu 11.04。

目前我有这段代码(使用pyUSB):

busses = usb.busses()
for bus in busses:
  devices = bus.devices
  for dev in devices:
    print repr(dev)
    print "Device:", dev.filename
    print "  idVendor: %d (0x%04x)" % (dev.idVendor, dev.idVendor)
    print "  idProduct: %d (0x%04x)" % (dev.idProduct, dev.idProduct)
    print "Manufacturer:", dev.iManufacturer
    print "Serial:", dev.iSerialNumber
    print "Product:", dev.iProduct

问题是我没有得到想要的输出,下面是一个例子:

<usb.legacy.Device object at 0x1653990>
Device: 
  idVendor: 4046 (0x0fce)
  idProduct: 53411 (0xd0a3)
Manufacturer: 1
Serial: 3
Product: 2

首先,我没有得到文件名,这对我来说是最重要的。我猜这个文件名就是/dev/ttyACM0之类的部分。其次,我认为每个USB设备都有一个UID,或者我应该使用供应商ID或产品ID吗?


显然我有一些设置问题,我觉得我使用了错误的USB库(现在用的是libusb0.1)。这就是为什么我得到的设备(dev.filename)字符串是空的。如果有人能告诉我他们使用的操作系统、USB库和PyUSB的版本,我想这会解决我的问题。

7 个回答

5

对于一个使用旧版USB和libusb-1.0的系统,这种方法可以用来获取各种实际的字符串。我以厂商和产品为例来说明。这种方法可能会产生一些输入输出操作,因为它实际上是从设备中读取信息(至少第一次是这样)。有些设备不提供这些信息,所以如果假设它们会提供而实际上没有,就会出现错误;没关系,我们可以忽略这个错误。

import usb.core
import usb.backend.libusb1

busses = usb.busses()
for bus in busses:
    devices = bus.devices
    for dev in devices:
        if dev != None:
            try:
                xdev = usb.core.find(idVendor=dev.idVendor, idProduct=dev.idProduct)
                if xdev._manufacturer is None:
                    xdev._manufacturer = usb.util.get_string(xdev, xdev.iManufacturer)
                if xdev._product is None:
                    xdev._product = usb.util.get_string(xdev, xdev.iProduct)
                stx = '%6d %6d: '+str(xdev._manufacturer).strip()+' = '+str(xdev._product).strip()
                print stx % (dev.idVendor,dev.idProduct)
            except:
                pass
44

如果你在使用Windows系统,可以使用pywin32这个工具(旧链接:请看下面的更新)。

我在这里找到一个例子:

import win32com.client

wmi = win32com.client.GetObject ("winmgmts:")
for usb in wmi.InstancesOf ("Win32_USBHub"):
    print usb.DeviceID

更新于2020年4月:

从218版本开始的'pywin32'发布版本可以在这里找到,当前版本是227。

81

我能想到一个简单的代码,像这样。

因为所有的USB接口都可以通过 /dev/bus/usb/< bus >/< device > 来访问。

对于生成的ID,即使你拔掉设备再重新插上(可能是插到其他的接口),这个ID也是一样的。

import re
import subprocess
device_re = re.compile("Bus\s+(?P<bus>\d+)\s+Device\s+(?P<device>\d+).+ID\s(?P<id>\w+:\w+)\s(?P<tag>.+)$", re.I)
df = subprocess.check_output("lsusb")
devices = []
for i in df.split('\n'):
    if i:
        info = device_re.match(i)
        if info:
            dinfo = info.groupdict()
            dinfo['device'] = '/dev/bus/usb/%s/%s' % (dinfo.pop('bus'), dinfo.pop('device'))
            devices.append(dinfo)
print devices

这里的示例输出将是:

[
{'device': '/dev/bus/usb/001/009', 'tag': 'Apple, Inc. Optical USB Mouse [Mitsumi]', 'id': '05ac:0304'},
{'device': '/dev/bus/usb/001/001', 'tag': 'Linux Foundation 2.0 root hub', 'id': '1d6b:0002'},
{'device': '/dev/bus/usb/001/002', 'tag': 'Intel Corp. Integrated Rate Matching Hub', 'id': '8087:0020'},
{'device': '/dev/bus/usb/001/004', 'tag': 'Microdia ', 'id': '0c45:641d'}
]

代码已更新为Python 3

import re
import subprocess
device_re = re.compile(b"Bus\s+(?P<bus>\d+)\s+Device\s+(?P<device>\d+).+ID\s(?P<id>\w+:\w+)\s(?P<tag>.+)$", re.I)
df = subprocess.check_output("lsusb")
devices = []
for i in df.split(b'\n'):
    if i:
        info = device_re.match(i)
        if info:
            dinfo = info.groupdict()
            dinfo['device'] = '/dev/bus/usb/%s/%s' % (dinfo.pop('bus'), dinfo.pop('device'))
            devices.append(dinfo)
            
print(devices)

撰写回答