简体   繁体   English

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

[英]Simple way to query connected USB devices info in Python?

How can we query connected USB devices info in Python?我们如何在 Python 中查询连接的 USB 设备信息? I want to get UID Device Name (ex: SonyEricsson W660), path to device (ex: /dev/ttyACM0)我想获取 UID 设备名称(例如:SonyEricsson W660)、设备路径(例如:/dev/ttyACM0)

And also what would be the best Parameter out of above info to be used as identifying the device whenever it's connected again?还有什么是上述信息中的最佳参数,可在再次连接时用于识别设备? (UID?) (UID?)

I am working on Ubuntu 11.04.我正在研究 Ubuntu 11.04。

ATM I have this code (using pyUSB) 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

The problem is I don't get desired output, will paste one example:问题是我没有得到想要的 output,将粘贴一个示例:

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

First I don't get filename, it's most important to me.首先我没有得到文件名,这对我来说最重要。 I am assuming it is the /dev/ttyACM0 etc part.我假设它是 /dev/ttyACM0 等部分。 Second, I guess there was some UID of every USB device, or I should use both Vendor or Product id?其次,我猜每个 USB 设备都有一些 UID,或者我应该同时使用 Vendor 或 Product id?

EDIT: Apparently I have some setup issues, I think I am using wrong USB Library.编辑:显然我有一些设置问题,我想我使用了错误的 USB 库。 (using libusb0.1) ATM. (使用 libusb0.1)ATM。 That's why I get Device (dev.filename) string empty.这就是为什么我让 Device (dev.filename) 字符串为空。 If someone can please just tell that on what operating system he is using what USB Library and what version of PyUSB I think it will solve my problems.如果有人可以请告诉他在什么操作系统上使用什么 USB 库和 PyUSB 的哪个版本我认为它将解决我的问题。

I can think of a quick code like this.我可以想到这样的快速代码。

Since all USB ports can be accessed via /dev/bus/usb/< bus >/< device >由于所有USB端口都可以通过/dev/bus/usb/<bus>/<device>访问

For the ID generated, even if you unplug the device and reattach it [ could be some other port ].对于生成的 ID,即使您拔下设备并重新连接它[可能是其他端口]。 It will be the same.它会是一样的。

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

Sample output here will be:样品 output 将是:

[
{'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'}
]

Code Updated for Python 3为 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)

If you are working on windows, you can use pywin32 (old link: see update below).如果您正在使用 windows,您可以使用pywin32 (旧链接:请参阅下面的更新)。

I found an example here :我在这里找到了一个例子:

import win32com.client

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

Update Apr 2020: 2020 年 4 月更新:

'pywin32' release versions from 218 and up can be found here at github.可以在github找到 218 及更高版本的“pywin32”发布版本。 Current version 227.当前版本 227。

For a system with legacy usb coming back and libusb-1.0, this approach will work to retrieve the various actual strings.对于带有旧版 usb 和 libusb-1.0 的系统,此方法将用于检索各种实际字符串。 I show the vendor and product as examples.我以供应商和产品为例。 It can cause some I/O, because it actually reads the info from the device (at least the first time, anyway.) Some devices don't provide this information, so the presumption that they do will throw an exception in that case;它可能会导致一些 I/O,因为它实际上是从设备读取信息(至少是第一次)。有些设备不提供此信息,因此在这种情况下假设它们会抛出异常; that's ok, so we pass.没关系,所以我们通过了。

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

For linux, I wrote a script called find_port.py which you can find here: https://github.com/dhylands/usb-ser-mon/blob/master/usb_ser_mon/find_port.py对于 linux,我编写了一个名为 find_port.py 的脚本,您可以在此处找到: https://github.com/dhylands/usb-ser-mon/blob/master/usb_ser_mon/find_port.py

It uses pyudev to enumerate all tty devices, and can match on various attributes.它使用 pyudev 枚举所有 tty 设备,并且可以匹配各种属性。

Use the --list option to show all of the know USB serial ports and their attributes.使用 --list 选项显示所有已知的 USB 串行端口及其属性。 You can filter by VID, PID, serial number, or vendor name.您可以按 VID、PID、序列号或供应商名称进行过滤。 Use --help to see the filtering options.使用 --help 查看过滤选项。

find_port.py prints the /dev/ttyXXX name rather than the /dev/usb/... name. find_port.py 打印 /dev/ttyXXX 名称而不是 /dev/usb/... 名称。

您可以尝试libusb绑定

When I run your code, I get the following output for example.例如,当我运行您的代码时,我得到以下 output。

<usb.Device object at 0xef38c0>
Device: 001
  idVendor: 7531 (0x1d6b)
  idProduct: 1 (0x0001)
Manufacturer: 3
Serial: 1
Product: 2

Noteworthy are that a) I have usb.Device objects whereas you have usb.legacy.Device objects, and b) I have device filenames.值得注意的是 a) 我有usb.Device对象,而你有usb.legacy.Device对象,并且 b) 我有设备文件名。

Each usb.Bus has a dirname field and each usb.Device has the filename.每个usb.Bus都有一个dirname字段,每个usb.Device都有文件名。 As you can see, the filename is something like 001 , and so is the dirname.如您所见,文件名类似于001 ,目录名也是如此。 You can combine these to get the bus file.您可以结合这些来获取总线文件。 For dirname=001 and filname=001 , it should be something like /dev/bus/usb/001/001.对于dirname=001filname=001 ,它应该类似于 /dev/bus/usb/001/001。

You should first, though figure out what this "usb.legacy" situation is.您应该首先弄清楚这种“usb.legacy”情况是什么。 I'm running the latest version and I don't even have a legacy sub-module.我正在运行最新版本,我什至没有legacy子模块。

Finally, you should use the idVendor and idProduct fields to uniquely identify the device when it's plugged in.最后,您应该使用idVendoridProduct字段在插入设备时唯一标识设备。

If you just need the name of the device here is a little hack which i wrote in bash.如果您只需要设备的名称,这里是我在 bash 中写的一个小技巧。 To run it in python you need the following snippet.要在 python 中运行它,您需要以下代码段。 Just replace $1 and $2 with Bus number and Device number eg 001 or 002.只需将 $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}'")

Alternately you can save it as a bash script and run it from there too.或者,您可以将其保存为 bash 脚本并从那里运行它。 Just save it as a bash script like foo.sh make it executable.只需将其保存为 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

Then call it in python script as然后在 python 脚本中调用它

import os
os.system('foo.sh')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM