在 Python 中查询连接的 USB 设备信息的简单方法?
Posted
技术标签:
【中文标题】在 Python 中查询连接的 USB 设备信息的简单方法?【英文标题】:Simple way to query connected USB devices info in Python? 【发布时间】:2011-12-27 23:03:09 【问题描述】:我们如何在 Python 中查询连接的 USB 设备信息? 我想获取 UID 设备名称(例如:SonyEricsson W660)、设备路径(例如:/dev/ttyACM0)
还有什么是上述信息中最好的参数,用于在再次连接时识别设备? (UID?)
我正在开发 Ubuntu 11.04。
ATM 我有这个代码(使用 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,或者我应该同时使用 Vendor 或 Product id?
编辑:显然我有一些设置问题,我认为我使用了错误的 USB 库。 (使用 libusb0.1)ATM。这就是为什么我将 Device (dev.filename) 字符串设为空的原因。如果有人能告诉我他在什么操作系统上使用什么 USB 库和什么版本的 PyUSB,我认为它将解决我的问题。
【问题讨论】:
这可能对***.com/questions/5109879/usb-devices-udev-and-d-busa 有所帮助。 感谢lionbest,从长远来看它可能会有所帮助,目前我只关心查询它们:) 【参考方案1】:我能想到这样的快速代码。
由于所有 USB 端口都可以通过 /dev/bus/usb/
对于生成的 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)
【讨论】:
很棒的代码,谢谢。无需依赖任何外部库即可工作,并为我提供我想要的东西。确切地。谢谢。 伙伴你能澄清一件事吗?我得到以下信息:`/dev/bus/usb/004/002 22b8:4902 Motorola PCS Triplet GSM Phone (AT)` 这是我要连接的设备,但是当我使用 gammu 时,我得到了这个:@987654324 @ 有什么想法(我试过用 sudo 运行脚本)? 嗨,我对 Gammu 的经验很少,但是你能粘贴你的配置文件吗?让我看看。 Gammu 在这里不太相关,我只想知道当我插入 GSM 调制解调器时,dmesg 显示它已注册为 ACM 设备并连接到 /dev/ttyACM0 端口,现在从该端口与调制解调器的连接完美无缺。但是 lsubs 返回的是“/dev/bus...../002”,我无法连接到该设备。您确定使用路径较长的设备应该像从 /dev/ttyACM0 路径中使用它一样工作吗? 在 windows 中,我已经尝试使用您的代码,但不支持 lsusb。我遇到了这个问题,你能帮我解决 lsusb 吗?【参考方案2】:如果您在 Windows 上工作,您可以使用pywin32
(旧链接:请参阅下面的更新)。
我找到了一个例子here:
import win32com.client
wmi = win32com.client.GetObject ("winmgmts:")
for usb in wmi.InstancesOf ("Win32_USBHub"):
print usb.DeviceID
2020 年 4 月更新:
'pywin32' 218 及更高版本可以在 github 上找到 here。当前版本 227。
【讨论】:
【参考方案3】:对于旧版 USB 回归和 libusb-1.0 的系统,这种方法可以检索各种实际字符串。我以供应商和产品为例。它可能会导致一些 I/O,因为它实际上是从设备读取信息(至少是第一次,无论如何)。某些设备不提供此信息,因此在这种情况下假设它们会抛出异常;没关系,所以我们通过了。
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
【讨论】:
【参考方案4】:对于 linux,我编写了一个名为 find_port.py 的脚本,您可以在这里找到它: https://github.com/dhylands/usb-ser-mon/blob/master/usb_ser_mon/find_port.py
它使用pyudev枚举所有tty设备,并且可以匹配各种属性。
使用 --list 选项显示所有已知的 USB 串行端口及其属性。您可以按 VID、PID、序列号或供应商名称进行过滤。使用 --help 查看过滤选项。
find_port.py 打印 /dev/ttyXXX 名称而不是 /dev/usb/... 名称。
【讨论】:
【参考方案5】:当我运行您的代码时,例如,我得到以下输出。
<usb.Device object at 0xef38c0>
Device: 001
idVendor: 7531 (0x1d6b)
idProduct: 1 (0x0001)
Manufacturer: 3
Serial: 1
Product: 2
值得注意的是 a) 我有 usb.Device
对象,而你有 usb.legacy.Device
对象,并且 b) 我有设备文件名。
每个usb.Bus
都有一个dirname
字段,每个usb.Device
都有文件名。如您所见,文件名类似于001
,目录名也是如此。您可以结合这些来获取总线文件。对于dirname=001
和filname=001
,它应该类似于/dev/bus/usb/001/001。
您应该首先弄清楚这种“usb.legacy”情况是什么。我正在运行最新版本,我什至没有 legacy
子模块。
最后,您应该使用idVendor
和idProduct
字段来唯一标识插入时的设备。
【讨论】:
感谢您对我的问题的透彻分析。是的,我很困惑,如您所见,我将 Device 参数设为空。你能告诉我你使用的是什么USB库吗?像 libusb0.1 或 OpenUSB 等?还有你用的是什么操作系统?我从 Github btw 下载了最新的 pyUSB。 你好,伙计,你能给我上面的信息吗?这将对我有很大帮助。谢谢。 抱歉,这些天我的互联网访问受限。我在最新的 Arch Linux 系统上使用了 pyusb 0.4.3。 我之前不是很清楚;我正在使用最新的 stable 版本。还有正在开发中的 1.x 系列。 谢谢伙伴 :) 但由于我不需要在 USB 设备上读写,只需查询它们,正确的答案要求我不依赖 pyUSB,因此我正在使用该 ATM。【参考方案6】:如果您只需要设备的名称,这里是我用 bash 编写的一个小技巧。要在 python 中运行它,您需要以下 sn-p。只需将 $1 和 $2 替换为总线编号和设备编号,例如 001 或 002。
import os
os.system("lsusb | grep \"Bus $1 Device $2\" | sed 's/\// /' | awk 'for(i=7;i<=NF;++i)print $i'")
您也可以将其保存为 bash 脚本并从那里运行它。只需将其保存为 bash 脚本,如 foo.sh 即可使其可执行。
#!/bin/bash
myvar=$(lsusb | grep "Bus $1 Device $2" | sed 's/\// /' | awk 'for(i=7;i<=NF;++i)print $i')
echo $myvar
然后在python脚本中调用它为
import os
os.system('foo.sh')
【讨论】:
我一会儿试试再回来 Qasim simple lsubs 给了我这样的信息: Bus 002 Device 002: ID 413c:1003 Dell Computer Corp. Keyboard Hub Bus 002 Device 003: ID 413c:2010 Dell Computer Corp. Keyboard which is missing one我需要的最重要的东西它映射到的实际文件名(例如:/dev/ttyACM0) 你可以写一个 udev 规则并创建一个符号链接/dev/ttyACM<x> -> /dev/mydevice
,如果你要打包这个 - 没问题,只需将规则放入包中(确保文件名不会冲突或回显规则到安装后脚本中的现有文件中)。否则,您可以使用 usbfs(通常是 /proc/bus/usb/
)或 udev 命令(不确定它叫什么)来查询它。以上是关于在 Python 中查询连接的 USB 设备信息的简单方法?的主要内容,如果未能解决你的问题,请参考以下文章