Python IndexError:列表索引超出范围。无法通过索引访问

时间:2017-03-26 04:06:28

标签: python pyserial index-error

我正在使用pySerial来读取TTL字节流。读取两个字节:

CheckSumByte = [ b for b in ser.read(2)]
print( CheckSumByte)
print( type(CheckSumByte))
print( str(len(CheckSumByte)))
print( CheckSumByte[0])

输出:

[202, 87]
<class 'list'>
2
IndexError: list index out of range

我无法通过索引(0或1)访问CheckSumByte的任何元素。有什么问题?

这是我的代码:

while(ReadBufferCount < 1000):
    time.sleep(0.00002)
    InputBuffer = ser.inWaiting()
    if (InputBuffer > 0):
        FirstByte = ser.read(1)
        if ord(FirstByte) == 0xFA:
            while ser.inWaiting() < 21: pass
        IndexByte = ser.read(1)
        SpeedByte = [ b for b in ser.read(2)]
        DataByte0 = [ b for b in ser.read(4)]
        DataByte1 = [ b for b in ser.read(4)]
        DataByte2 = [ b for b in ser.read(4)]
        DataByte3 = [ b for b in ser.read(4)]
        CheckSumByte = [ b for b in ser.read(2)]
        print( CheckSumByte[0]) #Out of Range??`
Traceback (most recent call last):

  File "<ipython-input-6-5233b0a578b1>", line 1, in <module>
    runfile('C:/Users/Blair/Documents/Python/Neato XV-11 Lidar/Serial9.py', wdir='C:/Users/Blair/Documents/Python/Neato XV-11 Lidar')

  File "C:\Program Files (x86)\WinPython-32bit-3.4.3.3\python-3.4.3\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 682, in runfile
    execfile(filename, namespace)

  File "C:\Program Files (x86)\WinPython-32bit-3.4.3.3\python-3.4.3\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 85, in execfile
    exec(compile(open(filename, 'rb').read(), filename, 'exec'), namespace)

  File "C:/Users/Blair/Documents/Python/Neato XV-11 Lidar/Serial9.py", line 88, in <module>
    print( CheckSumByte[0]) #Out of Range??

IndexError: list index out of range

肯尼:谢谢。两个字节更简单:

    CheckSumByte.append(ser.read(1))
    CheckSumByte.append(ser.read(1))

工作正常,但很尴尬。这些项是字节类型。如何使用列表推导将项添加到列表中?我想避免追加函数,因为它很慢。

我注意到当CheckSumByte的项是整数时它不起作用。 Python 3列表理解是否需要特殊格式才能将字节添加为字节(不转换为整数)?

2 个答案:

答案 0 :(得分:1)

根据您最近的评论,您已将ser构建为:

ser = serial.Serial(
    port=PortName, baudrate=115200, parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, 
    timeout=0)

根据documentation,这意味着ser 非阻止(尽管你断言它是阻止的!)。

由于它处于非阻塞模式,因此绝对没有理由期望ser.read(n)准确返回n个字节。相反,如果您希望阅读n字节,则应该:

  • 在构造函数中构造ser作为阻塞(使用timeout=None);或
  • 循环,同时监控实际读取的字节数(就像读取网络套接字时一样)

后者例如意味着如果您希望阅读n字节,则需要执行以下操作:

def read_exactly(ser, n):
    bytes = b""

    while len(bytes) < n:
        bytes += ser.read(n - len(bytes))

    return bytes

在您的特定情况下,您似乎正在监视输入缓冲区,以确保有足够的数据用于以下读取。但是这种监控只发生在某些的时间,而不是所有。因此,当FirstByte != 0xFA时,除非采用上面给出的方法之一,否则你可以耗尽读缓冲区。

答案 1 :(得分:0)

donkopotamus - 你找到了答案。我混淆了阻止条款。我设置超时= 0来尝试其他设置。你是对的,ser可以读零字节。我忘了把它设置回超时=无。现在总是读取一些字节。没有更多的IndexError。非常感谢你。