Python打印语句修复了OverflowError
我正在破解一个安全系统的录像机,想用Python(2.6版本)添加一些运动捕捉和其他有趣的功能。我从Java中反编译出来的一个函数并成功转换成Python,代码如下:
def ToInt(abyte0, i):
if(abyte0[i] >= 0):
j = abyte0[i]
print "A " + str(j)
else:
j = 256 + abyte0[i]
if abyte0[i + 1] >= 0:
j = j + (abyte0[i + 1] * 256)
print "A " + str(j)
else:
j = j + (256 + abyte0[i + 1]) * 256
if abyte0[i + 2] >= 0:
j = j+ abyte0[i + 2] * 256 * 256
print "A " + str(j)
else:
j = j + (256 + abyte0[i + 2]) * 256 * 256
if abyte0[i + 3] >= 0:
j = j + abyte0[i + 3] * 256 * 256 * 256
print "A " + str(j)
else:
j = j + (256 + abyte0[i + 3]) * 256 * 256 * 256
return j
为了弄清楚事情的进展,我在代码里加了打印语句。现在功能正常了,我想把这些打印语句去掉,但却出现了错误!
Traceback (most recent call last):
File "C:\Users\...\videostuff.py", line 154, in <module>
ReadData(i)
File "C:\Users\..\videostuff.py", line 122, in ReadData
data = s.recv(DATA_SIZE)
OverflowError: long int too large to convert to int
看起来在从套接字读取返回值时,长整型转换成整型时出现了问题。但为什么在有打印语句的时候就没问题呢?
调用代码:
i = ToInt(data_string.tolist(), 0)
# First byte tells how big the data wil be
if i > 4 and (i - 4) > DATA_SIZE:
DATA_SIZE = i - 4
# line 122
data = s.recv(DATA_SIZE)
所有的代码:
import socket
from array import array
import Image
import StringIO
import sys
def ToInt(abyte0, i):
if(abyte0[i] >= 0):
j = abyte0[i]
#print "A " + str(j)
else:
j = 256 + abyte0[i]
if abyte0[i + 1] >= 0:
j = j + (abyte0[i + 1] * 256)
#print "A " + str(j)
else:
j = j + (256 + abyte0[i + 1]) * 256
if abyte0[i + 2] >= 0:
j = j+ abyte0[i + 2] * 256 * 256
#print "A " + str(j)
else:
j = j + (256 + abyte0[i + 2]) * 256 * 256
if abyte0[i + 3] >= 0:
j = j + abyte0[i + 3] * 256 * 256 * 256
#print "A " + str(j)
else:
j = j + (256 + abyte0[i + 3]) * 256 * 256 * 256
return j
def StrLen(abyte0):
for i in len(abyte0):
if abyte0[i] == 0:
return i
def StrLen(abyte0, i):
for j in len(abyte0):
if abyte0[i] == 0:
return i
else:
i = i + 1
def Connect(s):
out_header = array('B', [32, 0, 0, 0, 205, 0, 0, 0])
data = array('B', [0, 0, 0, 0, \
5, 0, 0, 0, \
0, 0, 0, 0, \
0, 0, 0, 0, \
0, 0, 0, 0, \
0, 0, 0, 0, \
0, 0, 0, 0 \
])
#print 'sending data: '
#print out_header.tostring()
#print out_header.buffer_info()
#print struct.unpack('BBBBBBBBB', out_header)
s.send(out_header)
s.send(data)
def ReadHeader():
global DATA_SIZE
global DATA_TYPE
DATA_SIZE = 32
# Read the reply header
data = s.recv(HEADER_SIZE)
data_string = array('B', data)
i = ToInt(data_string.tolist(), 0)
# First byte tells how big the data wil be
if i > 4 and (i - 4) > DATA_SIZE:
DATA_SIZE = i - 4
print "DATA_SIZE is " + str(DATA_SIZE)
# Second byte tells what the data is
DATA_TYPE = data_string[4]
#if DATA_TYPE == 1:
# print "Dunno"
#elif DATA_TYPE == 106:
# print "MESSAGE"
#elif DATA_TYPE == 207:
# print "IMAGE"
#elif DATA_TYPE == 0:
# print "FALSE"
#else:
# print "ERROR"
def ReadData(i):
global DATA_SIZE
#if DATA_SIZE > sys.maxint:
# DATA_SIZE = sys.maxint
data = s.recv(DATA_SIZE)
data_string = array('B', data)
#afile = open("Dataz.txt", 'w')
#data_string.tofile(afile)
#print data_string
abyte0 = data_string.tolist()
#draw image
image_w = ToInt(abyte0, 0)
image_h = ToInt(abyte0, 4)
# should be around 9k
image_data_length = ToInt(abyte0, 72)
datas = data_string[76:]
file1 = open("Dataz.jpg", 'wb')
datas.tofile(file1)
file1.close()
#print "Length of image data is: " + str(len(datas))
#file = StringIO.StringIO(datas)
#file1 = open("Dataz1.jpg", 'rb')
#image = Image.open(file1)
#image.show()
#Global variables
TCP_IP = '192.168.1.106'
TCP_PORT = 17860
HEADER_SIZE = 8
DATA_SIZE = 32
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
#Starts channel 1
Connect(s)
ReadHeader()
#first data contains the channel name and status
data = s.recv(DATA_SIZE)
data_string = array('B', data)
# Second data should be first image
ReadHeader()
ReadData(0)
for i in range(1, 20):
ReadHeader()
ReadData(i)
s.close()
2 个回答
0
这里有一个问题的例子
if abyte0[i + 3] >= 0:
j = j + abyte0[i + 3] * 256 * 256 * 256
#print "A " + str(j)
else:
j = j + (256 + abyte0[i + 3]) * 256 * 256 * 256
假设 j == 0
,abyte0 == ( 0, 0, 0, 0)
,还有 i == 0
>>> j + (256 + abyte0[i + 3]) * 256 * 256 * 256
4294967296L
结果是一个长整型的值。无论有没有 print
语句,这个语句都不太可能是正确的。问题中提到的“现在我已经让它工作了”这一部分,最开始可能就不完全真实。因此,“去掉打印语句后我就出错了”这句话也不太可能是真的。
4
如果你给socket.recv()传入一个大于2147483647(十六进制0x7fffffff)的值,Python会尝试使用长整型而不是普通整型。很明显,你的DATA_SIZE值被认为是超过这个范围的。
ToInt()的代码看起来是在尝试把单个字节组合成一个整数,但你可能没有正确处理转换,特别是在处理负值的部分。通常,当你把代码从类似C语言的语言(包括Java)转换过来时,最好用更高级的方式来表达代码,而不是逐个处理字节和字符。
建议你使用标准库中的struct模块来进行转换,而不是直接处理字节。确保你指定正确的字节顺序(大端或小端),这样才能得到正确的结果。例如,假设你的数据是一个4个字符的字符串,其中第一个字符代表最小值,下面的代码可能会适用:
>>> import struct
>>> i = struct.unpack('<L', '\x23\x45\x00\x73')[0]
>>> print i
1929397539
你可以通过查看上面提到的文档来理解和修改这段代码。