带有枚举列表的 Python(递归?)函数正在循环访问未知数据



我有一个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

很抱歉代码中无休止的打印!

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

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

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

但相反,它会遍历似乎不存在的数据,并且枚举列表似乎导致了这种情况,但我无法弄清楚原因。

这是一张打印,概述了我所解释的所有内容:

Chunk Length: 96
Last Chunk: b''
Arg Chunk: b'192#$$x00x00x00x00xffx00x00x00x00x00x00x01Vx9fx00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x17x00x00x00x00x00192#$$x00x00x00x00xfex00x00x00x00x00x00x01Vx9fx00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x17x00x00x00x00x00'
Start Chunk: b'192#$$x00x00x00x00xffx00x00x00x00x00x00x01Vx9fx00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x17x00x00x00x00x00192#$$x00x00x00x00xfex00x00x00x00x00x00x01Vx9fx00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x17x00x00x00x00x00'
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#$$x00x00x00x00xfex00x00x00x00x00x00x01Vx9fx00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x17x00x00x00x00x00'
Last Chunk: b''
Arg Chunk: b'x00192#$$x00x00x00x00xfex00x00x00x00x00x00x01Vx9fx00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x17x00x00x00x00x00'
Start Chunk: b'x00192#$$x00x00x00x00xfex00x00x00x00x00x00x01Vx9fx00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x17x00x00x00x00x00'
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 语句,有什么想法吗?它需要传递剩余的数据,以防当前块中有另一条记录。

编辑这可能是内存问题,我如何 del 在 for 循环语句中创建枚举列表:(我将尝试分配给 var 并在删除它之前遍历它。

这是一个递归编程问题。我只是将程序更改为返回自身而不是调用自己,并在基本情况下使其返回 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)

最新更新