【问题标题】:Python (recursive?) function with enumerated list is looping through unknown data具有枚举列表的 Python(递归?)函数正在遍历未知数据
【发布时间】:2018-04-19 14:52:42
【问题描述】:

我有一个 python 线程套接字,我有一个名为 handleData 的潜在递归函数(不确定它是否完全满足递归的条件)。

 def handleData(self, chunk):
    current_chunk = self.last_chunk.get(threading.currentThread(), b'') # not sure thread id is safe to use, will be recycled
    print('Last Chunk:', self.last_chunk.get(threading.currentThread(), b''))
    print('Arg Chunk:', chunk)
    current_chunk += chunk
    print('Start Chunk:', current_chunk)
    #data = enumerate(current_chunk) # Enumerate objs have no len and are not subscriptable (accessible through index positions)
    #print('Enumerated Data:', data)
    hash_dec = 35
    doller_dec = 36
    for idx, x in enumerate(current_chunk):
        print('On idx:', idx, 'Byte', x)
        if x == hash_dec and current_chunk[idx+1] == doller_dec and current_chunk[idx+2] == doller_dec:
            start = idx+3
            end = idx+44
            if end >= len(current_chunk):
                 print('Index out of range')
                 self.last_chunk[threading.currentThread()] = current_chunk[idx:]
                 print('Last Chunk:', self.last_chunk[threading.currentThread()])
                 return
            else:
                record = current_chunk[start:end]
                # do math get values
                print('Printing Values')
                self.printValues(record)
                # need to save last chunk as everything after record
                ##self.last_chunk[threading.currentThread()] = current_chunk[end:]
                ##return
                ## THIS METHOD IS FAST when 48 bytes come in, does not work correctly for larger chunks
                # or recursively call this function but make self.last_chunk = '' before hand
                self.last_chunk[threading.currentThread()] = b''
                if self.record_counter > 50:
                    exit()
                print('Ending Chunk:', current_chunk[end:])
                self.handleData(current_chunk[end:])
                ## Likely gets wasteful when chunks are 48 bytes because it will call itself with \n (110), get returned by the if, have more data again after being called again

对不起,代码中没完没了的打印!

if 记录>50 是因为这个递归函数变成了无限循环

字节由套接字接收并传递给handleData。所以它有一大块字节进行操作,如果它成功地从字节中读取了一条数据记录,它将剩余的未读数据传回给它自己。

发生的情况是它最终将最后一个字节传递给自己,此时它应该意识到这里没有什么重要的,结束循环并让主套接字循环用一个新块调用它自己。

但相反,它遍历似乎不存在的数据及其似乎导致此问题的枚举列表,但我无法弄清楚原因。

这是我解释的所有内容的打印:

Chunk Length: 96
Last Chunk: b''
Arg Chunk: b'192#$$\x00\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x01V\x9f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x00\x00192#$$\x00\x00\x00\x00\xfe\x00\x00\x00\x00\x00\x00\x01V\x9f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x00\x00'
Start Chunk: b'192#$$\x00\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x01V\x9f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x00\x00192#$$\x00\x00\x00\x00\xfe\x00\x00\x00\x00\x00\x00\x01V\x9f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x00\x00'
On idx: 0 Byte 49
On idx: 1 Byte 57
On idx: 2 Byte 50
On idx: 3 Byte 35
Printing Values
0x0 0x0 0x0 0xff000000
Reader: 5888 Sensor: 87711 Age: 0xff000000 LastAge: 0xff000000 AgeDiff: 0x0 Record: 1
Ending Chunk: b'\x00192#$$\x00\x00\x00\x00\xfe\x00\x00\x00\x00\x00\x00\x01V\x9f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x00\x00'
Last Chunk: b''
Arg Chunk: b'\x00192#$$\x00\x00\x00\x00\xfe\x00\x00\x00\x00\x00\x00\x01V\x9f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x00\x00'
Start Chunk: b'\x00192#$$\x00\x00\x00\x00\xfe\x00\x00\x00\x00\x00\x00\x01V\x9f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x00\x00'
On idx: 0 Byte 0
On idx: 1 Byte 49
On idx: 2 Byte 57
On idx: 3 Byte 50
On idx: 4 Byte 35
Printing Values
0x0 0x0 0x0 0xfe000000
Reader: 5888 Sensor: 87711 Age: 0xfe000000 LastAge: 0xff000000 AgeDiff: -0x1000000 Record: 2
Ending Chunk: b'\x00'
Last Chunk: b''
Arg Chunk: b'\x00'
Start Chunk: b'\x00'
On idx: 0 Byte 0
On idx: 5 Byte 36
On idx: 6 Byte 36
On idx: 7 Byte 0
On idx: 8 Byte 0
On idx: 9 Byte 0
On idx: 10 Byte 0
On idx: 11 Byte 254
On idx: 12 Byte 0
On idx: 13 Byte 0
On idx: 14 Byte 0
On idx: 15 Byte 0
On idx: 16 Byte 0
On idx: 17 Byte 0
On idx: 18 Byte 1
On idx: 19 Byte 86
On idx: 20 Byte 159
On idx: 21 Byte 0
On idx: 22 Byte 0
On idx: 23 Byte 0
On idx: 24 Byte 0
On idx: 25 Byte 0
On idx: 26 Byte 0
On idx: 27 Byte 0
On idx: 28 Byte 0
On idx: 29 Byte 0
On idx: 30 Byte 0
On idx: 31 Byte 0
On idx: 32 Byte 0
On idx: 33 Byte 0
On idx: 34 Byte 0
On idx: 35 Byte 0
On idx: 36 Byte 0
On idx: 37 Byte 0
On idx: 38 Byte 0
On idx: 39 Byte 0
On idx: 40 Byte 0
On idx: 41 Byte 0
On idx: 42 Byte 0
On idx: 43 Byte 23
On idx: 44 Byte 0
On idx: 45 Byte 0
On idx: 46 Byte 0
On idx: 47 Byte 0
On idx: 48 Byte 0
On idx: 4 Byte 36
On idx: 5 Byte 36
On idx: 6 Byte 0
On idx: 7 Byte 0
On idx: 8 Byte 0
On idx: 9 Byte 0
On idx: 10 Byte 255
On idx: 11 Byte 0
On idx: 12 Byte 0
On idx: 13 Byte 0
On idx: 14 Byte 0
On idx: 15 Byte 0
On idx: 16 Byte 0
On idx: 17 Byte 1
On idx: 18 Byte 86
On idx: 19 Byte 159
On idx: 20 Byte 0
On idx: 21 Byte 0
On idx: 22 Byte 0
On idx: 23 Byte 0
On idx: 24 Byte 0
On idx: 25 Byte 0
On idx: 26 Byte 0
On idx: 27 Byte 0
On idx: 28 Byte 0
On idx: 29 Byte 0
On idx: 30 Byte 0
On idx: 31 Byte 0
On idx: 32 Byte 0
On idx: 33 Byte 0
On idx: 34 Byte 0
On idx: 35 Byte 0
On idx: 36 Byte 0
On idx: 37 Byte 0
On idx: 38 Byte 0
On idx: 39 Byte 0
On idx: 40 Byte 0
On idx: 41 Byte 0
On idx: 42 Byte 23
On idx: 43 Byte 0
On idx: 44 Byte 0
On idx: 45 Byte 0
On idx: 46 Byte 0
On idx: 47 Byte 0
On idx: 48 Byte 49
On idx: 49 Byte 57
On idx: 50 Byte 50
On idx: 51 Byte 35
Printing Values
0x0 0x0 0x0 0xfe000000
Reader: 5888 Sensor: 87711 Age: 0xfe000000 LastAge: 0xfe000000 AgeDiff: 0x0 Record: 3
Ending Chunk: b'\x00'

我需要更改将剩余数据传递回函数的方式,以便我停止发送读取记录的最后一个字节(b'/x00'),但我宁愿不做另一个 if 语句,有什么想法吗?它需要传递剩余的数据,以防当前块中有另一条记录。

编辑 这可能是内存问题吗,我如何删除在 for 循环语句中创建的枚举列表:( 我将尝试分配给 var 并在删除之前对其进行迭代。

【问题讨论】:

  • 这是因为它不是递归函数,坦率地说是递归的疯狂尝试:P

标签: python sockets byte enumerate


【解决方案1】:

这是一个递归编程问题。我只是将程序更改为返回自身而不是调用自身,并让它在基本情况下返回 true(尽管我认为 true 并不重要)。

我使用模块 pdb(python 调试器)来解决这个问题,非常好的工具!

我在 vim 中使用 :!python % 运行代码 并且使用 pdb.set_trace() 在函数的开头创建一个断点,我可以使用 n(ext) 单步执行每一行。

这让我看到它会返回多少次,我意识到我的问题:)

这里是固定代码:

def handleData(self, chunk):
    pdb.set_trace()
    # Assigns the previous unprocessed byte string to the current_chunk, will be empty byte string if none found
    current_chunk = self.last_chunk.get(threading.current_thread(), b'')
    # Adds the argument chunk to the previous chunk (if called by itself or from main loop)
    current_chunk += chunk
    current_len = len(current_chunk)
    # Decimal values of ASCII chars #, $
    hash_dec = 35
    dollar_dec = 36
    idx = 0

    # For loop to iterate over the byte string
    for x in current_chunk:
        # if current index is # and the next two indexs are $ then we have found a record delimiter
        if x == hash_dec and current_chunk[idx+1] == dollar_dec and current_chunk[idx+2] == dollar_dec:
            # Index positions for list slice
            start = idx+3
            end = idx+45

            # if end slice index is greater than range of list
            if end > current_len:
                print('Index out of range')
                self.last_chunk[threading.current_thread()] = current_chunk[idx:]
                return True

            self.printValues(current_chunk[start:end])

            self.last_chunk[threading.current_thread()] = b''

            #if end == current_len:
                #print('No more bytes left in chunk!')
                #return True

            print('Ending Chunk:', current_chunk[end:])
            return self.handleData(current_chunk[end:])

        idx += 1

如果有人对此代码有任何其他想法,我很想听听他们的意见! 块的大小直接反映了它可能必须通过自身返回多少次才能到达主循环,所以我正在考虑将 socket.recv() 保持在低字节大小(是 4096 - 考虑 1024)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-01
    • 2016-01-23
    • 1970-01-01
    • 2019-04-03
    • 2019-08-03
    • 2012-02-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多