You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

读取USB设备时触发Index Out of Range错误的排查求助

USB设备读取索引越界问题修复

问题分析

触发IndexError的核心原因是:在非阻塞模式下,simpad.read(11)并非每次都能返回完整的11字节数据——当设备还没准备好数据时,会返回空列表或长度不足的字节数组,这时直接访问readout[2]就会超出索引范围。你的开发机上数据传输稳定,所以没出现问题,但其他PC可能因为USB驱动差异、设备初始化延迟等原因出现读取不完整的情况。

另外,你在每次run()循环里重复打开USB设备,这种反复初始化的操作会加剧设备通信的不稳定性,也是潜在问题。

解决方案

  1. 提前初始化USB设备:只在程序启动时打开一次设备,避免反复打开/关闭
  2. 增加读取有效性判断:每次读取后先检查返回数据的长度,只有长度符合要求时才处理数据
  3. 容错处理:读取失败或数据异常时跳过本次循环,继续等待下一次读取

修改后的代码

from tkinter import *
from PIL import ImageTk, Image
import hid
import sys
import os

def resource_path(relative_path):
    """ 获取资源的绝对路径,兼容开发环境和PyInstaller打包 """
    try:
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")
    return os.path.join(base_path, relative_path)

win = Tk("Test")
win.geometry("460x410")
win.config(bg="grey")
Btn = Button(win, text="ok", activebackground='gray', bg='grey', bd=0)

path = resource_path("Animation/")

List = ['000.png',
        '001.png', '002.png', '003.png', '004.png', '005.png', '006.png', '007.png', '008.png', '009.png', '010.png',
        '011.png', '012.png', '013.png', '014.png', '015.png', '016.png', '017.png', '018.png', '019.png', '020.png',
        '021.png', '022.png', '023.png', '024.png', '025.png', '026.png', '027.png', '028.png', '029.png', '030.png',
        '031.png', '032.png', '033.png', '034.png', '035.png', '036.png', '037.png', '038.png', '039.png', '040.png',
        '041.png', '042.png', '043.png', '044.png', '045.png', '046.png', '047.png', '048.png', '049.png', '050.png',
        '051.png', '052.png', '053.png', '054.png', '055.png', '056.png', '057.png', '058.png', '059.png', '060.png',
        '061.png', '062.png', '063.png', '064.png', '065.png', '066.png', '067.png', '068.png', '069.png', '070.png',
        '071.png', '072.png', '073.png', '074.png', '075.png', '076.png', '077.png', '078.png', '079.png', '080.png',
        '081.png', '082.png', '083.png', '084.png', '085.png', '086.png', '087.png', '088.png', '089.png', '090.png',
        '091.png', '092.png', '093.png', '094.png', '095.png', '096.png', '097.png', '098.png', '099.png', '100.png',
        '101.png', '102.png', '103.png', '104.png', '105.png', '106.png', '107.png', '108.png', '109.png', '110.png',
        '111.png', '112.png', '113.png', '114.png', '115.png', '116.png', '117.png', '118.png', '119.png', '120.png',
        '121.png', '122.png', '123.png', '124.png', '125.png', '126.png', '127.png', '128.png', '129.png', '130.png',
        '131.png', '132.png', '133.png', '134.png', '135.png', '136.png', '137.png', '138.png', '139.png', '140.png',
        '141.png', '142.png', '143.png', '144.png', '145.png', '146.png', '147.png', '148.png', '149.png', '150.png',
        '151.png', '152.png', '153.png', '154.png', '155.png', '156.png', '157.png', '158.png', '159.png', '160.png',
        '161.png', '162.png', '163.png', '164.png', '165.png', '166.png', '167.png', '168.png', '169.png', '170.png',
        '171.png', '172.png', '173.png', '174.png', '175.png', '176.png', '177.png', '178.png', '179.png', '180.png',
        '181.png', '182.png', '183.png', '184.png', '185.png', '186.png', '187.png', '188.png', '189.png', '190.png',
        '191.png', '192.png', '193.png', '194.png', '195.png', '196.png', '197.png', '198.png', '199.png', '200.png',
        '201.png', '202.png', '203.png', '204.png', '205.png', '206.png', '207.png', '208.png', '209.png', '210.png',
        '211.png', '212.png', '213.png', '214.png', '215.png', '216.png', '217.png', '218.png', '219.png', '220.png',
        '221.png', '222.png', '223.png', '224.png', '225.png', '226.png', '227.png', '228.png', '229.png', '230.png',
        '231.png', '232.png', '233.png', '234.png', '235.png', '236.png', '237.png', '238.png', '239.png', '240.png',
        '241.png', '242.png', '243.png', '244.png', '245.png', '246.png', '247.png', '248.png', '249.png', '250.png',
        '251.png', '252.png', '253.png', '254.png', '255.png', '256.png', '257.png', '258.png', '259.png', '260.png',
        ]

def to_pil2(img, button, x, y, w, h):
    image = Image.open(img)
    image = image.resize((w, h))
    pic = ImageTk.PhotoImage(image)
    button['image'] = pic
    button.image = pic
    button.place(x=x, y=y)

label = Label(win, font=('Stencil', 30, 'bold'), bg='grey', fg='black')
label.place(x=5, y=5)

# 全局初始化USB设备,只执行一次
simpad = hid.device()
simpad.open(0x2341, 0x8037)
simpad.set_nonblocking(True)

def run():
    global simpad
    readout = simpad.read(11)
    
    # 先判断读取的数据长度是否足够,避免索引越界
    if len(readout) >= 3:
        read_x2 = readout[2]
        # 确保读取到的数值在List的索引范围内(0-260)
        if 0 <= read_x2 < len(List):
            to_pil2(path + List[read_x2], Btn, 5, 5, 450, 400)
            label['text'] = read_x2
        else:
            # 数值超出范围时的容错处理
            label['text'] = "Out of Range"
    else:
        # 读取数据不足时的提示
        label['text'] = "No Data"
    
    # 继续下一次循环
    win.after(10, run)
    print(readout)

run()
Btn["command"] = lambda: print('Freeze-test')

# 程序关闭时关闭USB设备,避免资源占用
def on_closing():
    simpad.close()
    win.destroy()

win.protocol("WM_DELETE_WINDOW", on_closing)
win.mainloop()

额外说明

  • 新增了程序关闭时的设备释放逻辑,避免USB设备被占用
  • 增加了read_x2的范围判断,防止因设备返回异常值导致图片路径错误
  • 移除了重复打开设备的操作,提升通信稳定性

内容的提问来源于stack exchange,提问作者Emanresu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 17:30:21