最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入解析Python如何利用PyUSB輕松操控USB設備

 更新時間:2026年01月05日 14:23:44   作者:蕭鼎  
本文將從?基礎概念、安裝配置、核心?API、實戰(zhàn)案例、調試技巧到高級應用,系統(tǒng)性地介紹?PyUSB,幫助你掌握如何用?Python?高效、安全地與?USB?設備交互,感興趣的小伙伴可以了解下

引言:為什么需要 PyUSB?

在嵌入式系統(tǒng)、工業(yè)自動化、物聯(lián)網(wǎng)(IoT)以及硬件交互開發(fā)中,與 USB 設備通信是一項常見但技術門檻較高的任務。傳統(tǒng)上,開發(fā)者需使用 C/C++ 編寫底層驅動或調用操作系統(tǒng)特定的 API(如 Windows 的 WinUSB、Linux 的 libusb),不僅代碼復雜,還缺乏跨平臺能力。

而 PyUSB 的出現(xiàn),徹底改變了這一局面。作為 Python 生態(tài)中用于 USB 通信的核心庫,PyUSB 提供了一套簡潔、統(tǒng)一、跨平臺的接口,讓開發(fā)者無需深入操作系統(tǒng)內核,即可通過幾行 Python 代碼讀寫 USB 設備、控制端點、枚舉設備信息,甚至實現(xiàn)自定義 HID(人機接口設備)或 CDC(通信設備類)協(xié)議。

本文將從 基礎概念、安裝配置、核心 API、實戰(zhàn)案例、調試技巧到高級應用,系統(tǒng)性地介紹 PyUSB,幫助你掌握如何用 Python 高效、安全地與 USB 設備交互。無論你是想讀取 USB 溫度傳感器、控制 LED 燈帶,還是開發(fā)自己的 USB 外設固件測試工具,PyUSB 都是你不可或缺的利器。

一、USB 基礎知識回顧

在深入 PyUSB 之前,有必要簡要了解 USB 協(xié)議的基本結構,這有助于理解后續(xù)的代碼邏輯。

1.1 USB 設備層級模型

一個 USB 設備由以下邏輯單元組成:

  • 設備(Device):物理 USB 設備本身,具有唯一的 Vendor ID(VID)和 Product ID(PID)。
  • 配置(Configuration):一個設備可有多個配置(通常為1),描述供電、接口數(shù)量等。
  • 接口(Interface):功能單元,如一個 USB 音頻設備可能包含“麥克風”和“揚聲器”兩個接口。
  • 端點(Endpoint):數(shù)據(jù)傳輸?shù)慕K點。分四種類型:
  • Control(控制):用于設備配置和狀態(tài)查詢(端點0,雙向);
  • Bulk(批量):高可靠、低實時性,如打印機、存儲設備;
  • Interrupt(中斷):低延遲、小數(shù)據(jù)量,如鍵盤、鼠標;
  • Isochronous(同步):高帶寬、容忍丟包,如攝像頭、音頻流。

注意:PyUSB 主要操作 端點 來進行數(shù)據(jù)收發(fā)。

1.2 標準請求與 Class 規(guī)范

USB 協(xié)議定義了標準設備請求(如 GET_DESCRIPTOR、SET_CONFIGURATION),同時也允許廠商自定義命令。此外,USB-IF 制定了多種 設備類(Device Class) 規(guī)范,如:

  • HID(Human Interface Device):鍵盤、鼠標、游戲手柄;
  • CDC(Communication Device Class):虛擬串口(如 Arduino);
  • MSC(Mass Storage Class):U 盤;
  • DFU(Device Firmware Upgrade):固件升級。

PyUSB 不依賴這些高層協(xié)議,它工作在 傳輸層,因此適用于任何 USB 設備——包括沒有標準驅動的“裸設備”。

二、PyUSB 安裝與環(huán)境配置

2.1 安裝 PyUSB

PyUSB 是純 Python 庫,但依賴底層 USB 后端(backend)。安裝命令如下:

pip install pyusb

注意:PyUSB 本身不包含后端實現(xiàn),需額外安裝支持庫。

2.2 后端選擇與配置

PyUSB 支持三種主流后端:

后端適用系統(tǒng)安裝方式
libusb1Linux / macOS / Windowssudo apt install libusb-1.0-0-dev (Linux) 或 libusb.org 下載 Windows DLL
libusb0舊版 Linux / Windows已基本淘汰,不推薦
OpenUSBSolaris極少使用

推薦使用 libusb1,因其跨平臺性好、維護活躍。

Windows 用戶特別說明:

  • 下載 libusb-1.0.dll
  • 將 DLL 文件放入 C:\Windows\System32 或 Python 腳本同目錄
  • 或使用 Zadig 工具為設備安裝 WinUSB 驅動(關鍵步驟?。?/li>

若未正確安裝驅動,Windows 會阻止用戶態(tài)程序訪問 USB 設備,報錯 Access denied 或 No backend available。

Linux 用戶權限問題:

默認情況下,普通用戶無權訪問 /dev/bus/usb/*。解決方法:

# 創(chuàng)建 udev 規(guī)則(以 VID=0x1234, PID=0x5678 為例)
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1234", ATTR{idProduct}=="5678", MODE="0666"' | sudo tee /etc/udev/rules.d/99-myusb.rules
sudo udevadm control --reload-rules && sudo udevadm trigger

三、PyUSB 核心 API 詳解

PyUSB 的設計哲學是“簡單即強大”。其核心模塊為 usb.core 和 usb.util。

3.1 枚舉與查找設備

使用 usb.core.find() 查找設備:

import usb.core
import usb.util

# 方法1:通過 VID/PID 查找
dev = usb.core.find(idVendor=0x1234, idProduct=0x5678)

# 方法2:查找所有設備
devices = usb.core.find(find_all=True)

# 方法3:自定義查找函數(shù)
def my_filter(dev):
    return dev.idVendor == 0x1234 and dev.manufacturer == "MyCompany"

dev = usb.core.find(custom_match=my_filter)

若未找到,返回 None;若找到多個且未用 find_all=True,拋出 ValueError。

3.2 設備信息獲取

一旦獲得 dev 對象(usb.core.Device 實例),可讀取其描述符:

print(f"Manufacturer: {usb.util.get_string(dev, dev.iManufacturer)}")
print(f"Product: {usb.util.get_string(dev, dev.iProduct)}")
print(f"Serial: {usb.util.get_string(dev, dev.iSerialNumber)}")

# 打印所有配置
for cfg in dev:
    print(f"Config {cfg.bConfigurationValue}")
    for intf in cfg:
        print(f"  Interface {intf.bInterfaceNumber}: {intf.bNumEndpoints} endpoints")
        for ep in intf:
            print(f"    EP {ep.bEndpointAddress:02x} ({'IN' if ep.bEndpointAddress & 0x80 else 'OUT'}), Type: {ep.bmAttributes & 0x03}")

注意:字符串描述符需通過 usb.util.get_string() 解碼,直接訪問 dev.iProduct 返回的是索引。

3.3 聲明接口與釋放內核驅動

在 Linux/macOS 上,若設備已被系統(tǒng)驅動占用(如 HID 鍵盤被內核接管),需先 分離內核驅動:

if dev.is_kernel_driver_active(0):  # 接口0
    dev.detach_kernel_driver(0)

操作完成后,應重新附加驅動(良好實踐):

dev.attach_kernel_driver(0)

Windows 通常無需此步驟(因使用 WinUSB 驅動時內核未接管)。

3.4 設置配置與聲明接口

大多數(shù)設備只需使用默認配置:

dev.set_configuration()  # 使用第一個配置
cfg = dev.get_active_configuration()
intf = cfg[(0, 0)]       # 獲取接口0,備用設置0

3.5 端點通信:讀寫數(shù)據(jù)

寫數(shù)據(jù)(OUT 端點):

# 假設端點地址為 0x01(OUT)
ep_out = usb.util.find_descriptor(intf, custom_match=lambda e: \
    usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT)

if ep_out:
    data = b'\x01\x02\x03\x04'
    bytes_written = dev.write(ep_out.bEndpointAddress, data, timeout=1000)
    print(f"Sent {bytes_written} bytes")

讀數(shù)據(jù)(IN 端點):

# 假設端點地址為 0x81(IN)
ep_in = usb.util.find_descriptor(intf, custom_match=lambda e: \
    usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN)

if ep_in:
    try:
        data = dev.read(ep_in.bEndpointAddress, ep_in.wMaxPacketSize, timeout=1000)
        print(f"Received: {data}")
    except usb.core.USBError as e:
        if e.errno == 110:  # 超時
            print("Read timeout")

關鍵參數(shù):

  • timeout:單位毫秒,避免無限阻塞;
  • wMaxPacketSize:端點最大包長,可作為讀緩沖區(qū)大小。

四、實戰(zhàn)案例:與自定義 USB 設備通信

假設我們有一個基于 STM32 的 USB CDC 設備(虛擬串口),但希望繞過操作系統(tǒng)串口驅動,直接通過 PyUSB 控制。

4.1 設備信息分析

首先,用 lsusb -v(Linux)或 USBTreeView(Windows)查看設備描述符:

Bus 001 Device 005: ID 0483:5740 STMicroelectronics Virtual COM Port
Device Descriptor:
  bcdUSB               2.00
  bDeviceClass          2 Communications
  bDeviceSubClass       0 
  bDeviceProtocol       0 
  idVendor           0x0483 STMicroelectronics
  idProduct          0x5740 Virtual COM Port
  ...
  Interface Descriptor:
    bInterfaceNumber     0
    bInterfaceClass      2 Communications
    bInterfaceSubClass   2 Abstract (modem)
    bInterfaceProtocol   1 AT-commands (v.25ter)
    Endpoint Descriptor:
      bEndpointAddress     0x81  EP 1 IN
      bmAttributes            3
        Transfer Type            Interrupt
      wMaxPacketSize     0x0008
    Endpoint Descriptor:
      bEndpointAddress     0x01  EP 1 OUT
      bmAttributes            2
        Transfer Type            Bulk

可見,該設備有兩個端點:0x81(IN,中斷)、0x01(OUT,批量)。

4.2 編寫通信腳本

import usb.core
import usb.util
import sys

# 查找設備
dev = usb.core.find(idVendor=0x0483, idProduct=0x5740)
if dev is None:
    raise ValueError('Device not found')

# 分離內核驅動(Linux/macOS)
if sys.platform != "win32":
    if dev.is_kernel_driver_active(0):
        dev.detach_kernel_driver(0)

# 設置配置
dev.set_configuration()

# 獲取接口
cfg = dev.get_active_configuration()
intf = cfg[(0, 0)]

# 查找端點
ep_out = usb.util.find_descriptor(
    intf,
    custom_match=lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT
)
ep_in = usb.util.find_descriptor(
    intf,
    custom_match=lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN
)

if not ep_out or not ep_in:
    raise ValueError("Endpoints not found")

# 發(fā)送 AT 命令
command = b"AT\r\n"
dev.write(ep_out.bEndpointAddress, command, timeout=1000)

# 讀取響應
try:
    response = dev.read(ep_in.bEndpointAddress, 64, timeout=1000)
    print("Response:", response.tobytes().decode('utf-8', errors='replace'))
except usb.core.USBError as e:
    print("Read error:", e)

運行結果可能為:

Response: AT
OK

此例展示了如何繞過 pyserial,直接與 CDC 設備通信,適用于需要低延遲或自定義協(xié)議的場景。

五、常見問題與調試技巧

5.1 “No backend available” 錯誤

原因:未安裝 libusb 或 DLL 未找到。

解決:

  • Linux:sudo apt install libusb-1.0-0-dev
  • Windows:將 libusb-1.0.dll 放入 PATH 或腳本目錄;
  • 指定后端:usb.core.find(backend=usb.backend.libusb1.get_backend())

5.2 “Access denied” 或 “Operation not permitted”

Linux:檢查 udev 規(guī)則,確保用戶有權限;

Windows:用 Zadig 為設備安裝 WinUSB 驅動(替換原有驅動);

macOS:可能需要禁用 SIP 或使用 IOKit 后端(較少見)。

5.3 讀寫超時或無響應

檢查端點方向是否正確(IN/OUT);

確認設備固件是否處于接收狀態(tài);

增加 timeout 值;

使用 USB 協(xié)議分析儀(如 Wireshark + USBPcap)抓包驗證。

5.4 設備被系統(tǒng)占用

在 Windows 上,HID 設備常被 hidusb.sys 占用,需用 Zadig 替換為 WinUSB;

在 Linux 上,使用 detach_kernel_driver()。

六、高級應用:構建 USB 測試框架

PyUSB 可用于自動化測試嵌入式設備的 USB 功能。例如,驗證設備在不同命令下的響應:

class USBDeviceTester:
    def __init__(self, vid, pid):
        self.dev = usb.core.find(idVendor=vid, idProduct=pid)
        assert self.dev, "Device not found"
        self.dev.set_configuration()
        self._setup_endpoints()

    def _setup_endpoints(self):
        cfg = self.dev.get_active_configuration()
        intf = cfg[(0, 0)]
        self.ep_out = ...  # find OUT
        self.ep_in = ...   # find IN

    def send_command(self, cmd: bytes) -> bytes:
        self.dev.write(self.ep_out.bEndpointAddress, cmd, timeout=2000)
        return self.dev.read(self.ep_in.bEndpointAddress, 256, timeout=2000).tobytes()

    def test_led_on(self):
        resp = self.send_command(b"LED ON\n")
        assert b"OK" in resp, "LED ON failed"

    def test_temperature(self):
        resp = self.send_command(b"TEMP?\n")
        temp = float(resp.strip())
        assert 20 <= temp <= 30, f"Invalid temperature: {temp}"

此類框架可集成到 CI/CD 流程中,實現(xiàn)硬件回歸測試。

七、PyUSB 與其他庫的對比

優(yōu)點缺點適用場景
PyUSB跨平臺、底層控制、靈活需處理 USB 協(xié)議細節(jié)自定義設備、協(xié)議開發(fā)
pyserial簡單易用僅限 CDC/串口設備Arduino、ESP32 通信
hidapi(via hid專為 HID 優(yōu)化僅支持 HID 類鍵盤、游戲手柄
libusb-py更底層已停止維護不推薦

結論:PyUSB 是通用 USB 通信的首選。

結語:讓 Python 成為你的 USB 開發(fā)利器

PyUSB 以極簡的 API 封裝了復雜的 USB 通信細節(jié),使 Python 開發(fā)者能夠輕松進入硬件交互領域。無論是快速原型驗證、自動化測試,還是構建跨平臺的設備管理工具,PyUSB 都提供了強大而可靠的支持。

然而,能力越大,責任越大。直接操作 USB 設備意味著你需要理解端點、傳輸類型、描述符等概念,并謹慎處理權限與資源釋放。建議在開發(fā)中始終遵循:

  • 先枚舉,再操作;
  • 及時釋放內核驅動;
  • 設置合理超時;
  • 異常處理全覆蓋。

最后,記?。鹤詈玫?USB 代碼,是那些即使設備拔掉也不會崩潰的代碼。

到此這篇關于深入解析Python如何利用PyUSB輕松操控USB設備的文章就介紹到這了,更多相關Python PyUSB控制USB設備內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Conda環(huán)境離線遷移全過程

    Conda環(huán)境離線遷移全過程

    這篇文章主要介紹了Conda環(huán)境離線遷移全過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-10-10
  • python 統(tǒng)計文件中的字符串數(shù)目示例

    python 統(tǒng)計文件中的字符串數(shù)目示例

    今天小編就為大家分享一篇python 統(tǒng)計文件中的字符串數(shù)目示例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12
  • Python中的查找算法代碼實例

    Python中的查找算法代碼實例

    這篇文章主要介紹了Python中的查找算法代碼實例,算法是解決一系列問題的清晰指令,也就是,能對一定規(guī)范的輸入,在有限的時間內獲得所要求的輸出,簡單來說,算法就是解決一個問題的具體方法和步驟,算法是程序的靈魂,需要的朋友可以參考下
    2023-07-07
  • Python使用Vagrant搭建開發(fā)環(huán)境的具體步驟

    Python使用Vagrant搭建開發(fā)環(huán)境的具體步驟

    使用 Vagrant 搭建開發(fā)環(huán)境是一個非常方便的方式,它可以幫助你快速創(chuàng)建、配置和管理虛擬機,確保開發(fā)環(huán)境的一致性,以下是使用 Vagrant 搭建開發(fā)環(huán)境的具體步驟,需要的朋友可以參考下
    2024-09-09
  • pycharm配置anaconda環(huán)境時找不到python.exe的兩種解決辦法

    pycharm配置anaconda環(huán)境時找不到python.exe的兩種解決辦法

    如果你在Anaconda中創(chuàng)建了虛擬環(huán)境,但是無法找到python.exe,可能是因為虛擬環(huán)境的Python路徑?jīng)]有添加到系統(tǒng)環(huán)境變量中,這篇文章主要給大家介紹了關于pycharm配置anaconda環(huán)境時找不到python.exe的兩種解決辦法,需要的朋友可以參考下
    2024-07-07
  • 關于python爬蟲模塊urllib庫詳解

    關于python爬蟲模塊urllib庫詳解

    這篇文章主要介紹了關于python爬蟲模塊urllib庫詳解,學習爬蟲,最初的操作便是模擬瀏覽器向服務端發(fā)出請求,這里我們就學習使用urlib庫的用法,需要的朋友可以參考下
    2023-07-07
  • Python采集電視劇《開端》彈幕做成詞云圖

    Python采集電視劇《開端》彈幕做成詞云圖

    大家好,本篇文章主要講的是Python采集電視劇《開端》彈幕做成詞云圖,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-01-01
  • 詳解matplotlib技巧之縮放和投影

    詳解matplotlib技巧之縮放和投影

    我們在使用matplotlib繪制圖形時,有兩個重要的技巧:一種是?Scale(縮放),一種是Projection(投影),縮放和投影在matplotlib繪圖中起著至關重要的作用,它們幫助我們更好地展示和理解數(shù)據(jù),本文將詳細的給大家介紹這兩個技巧,需要的朋友可以參考下
    2024-01-01
  • python利用tkinter實現(xiàn)屏保

    python利用tkinter實現(xiàn)屏保

    這篇文章主要為大家詳細介紹了python利用tkinter實現(xiàn)屏保,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • Python2.7版os.path.isdir中文路徑返回false的解決方法

    Python2.7版os.path.isdir中文路徑返回false的解決方法

    這篇文章主要為大家詳細介紹了Python2.7版os.path.isdir中文路徑返回false的解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-06-06

最新評論

开鲁县| 巴彦县| 巫山县| 巴林左旗| 金堂县| 孙吴县| 镶黄旗| 姜堰市| 柘城县| 蓬安县| 赤水市| 新源县| 桐乡市| 抚松县| 宣威市| 宝应县| 海淀区| 威信县| 梨树县| 丰镇市| 红安县| 龙泉市| 松原市| 泌阳县| 鱼台县| 崇阳县| 沾益县| 高邑县| 赣榆县| 广水市| 天全县| 丹巴县| 化德县| 巴林左旗| 怀远县| 巴里| 五台县| 宁德市| 永德县| 叙永县| 沙坪坝区|