[英]Python struct.unpack not working
我试图运行这个:
def ReadWord(fid,fmt,Addr):
fid.seek(Addr)
s = fid.readline(2)
s = unpack(fmt + 'h', s)
if(type(s) == tuple):
return s[0]
else:
return s
有:
len(s) = 2
len(fmt) = 1
calcsize(fmt) = 0
calcsize(fmt + 'h') = 2
但是,Python返回:
struct.error:unpack需要长度为4的字符串参数
根据python struct.unpack
文档 :
该字符串必须包含格式所需的数据量(len(字符串)必须等于calcsize(fmt))。
因此,如果我的字符串的长度是2并且fmt+'h'
calcsize也是2,为什么python说“unpack需要一个长度为4的字符串参数”?
编辑:
谢谢你的所有答案。 这是完整的代码:
http://qtwork.tudelft.nl/gitdata/users/guen/qtlabanalysis/analysis_modules/general/lecroy.py
因此,您可以在read_timetrace
函数中看到, fmt
在if...else
语句中设置为'<'
或'>'
。 打印确认了这一点。
但你也应该知道我正在使用windowsx64(工作)。
EDIT2
这是完整的追溯,对不起这个错误。
Traceback (most recent call last):
File "C:\Users\maxime.vast\Desktop\Test Campaign Template\Test Suite\Include\readLecroyTRCFile.py", line 139, in <module>
read_timetrace("C:\Users\maxime.vast\Desktop\Test Campaign Template\Test Suite\Traces\KL.ES.001.001.trc")
File "C:\Users\maxime.vast\Desktop\Test Campaign Template\Test Suite\Include\readLecroyTRCFile.py", line 60, in read_timetrace
WAVE_ARRAY_1 = ReadLong(fid, fmt, aWAVE_ARRAY_1)
File "C:\Users\maxime.vast\Desktop\Test Campaign Template\Test Suite\Include\readLecroyTRCFile.py", line 100, in ReadLong
s = unpack(fmt + 'l', s)
struct.error: unpack requires a string argument of length 4
[Finished in 0.2s]
EDIT3:
我通过read
替换了readline
并添加:
print "len(s) ", len(s)
print "len(fmt) ", len(fmt)
print "calcsize(fmt) ", calcsize(fmt)
print "calcsize(fmt + 'h') ", calcsize(fmt + 'h')
print "fmt ", fmt
ReadLong
功能。
这是新的追溯:
len(s) 4
len(fmt) 1
calcsize(fmt) 0
calcsize(fmt + 'h') 2
fmt <
len(s) 4
len(fmt) 1
calcsize(fmt) 0
calcsize(fmt + 'h') 2
fmt <
len(s) 4
len(fmt) 1
calcsize(fmt) 0
calcsize(fmt + 'h') 2
fmt <
len(s) 1
len(fmt) 1
calcsize(fmt) 0
calcsize(fmt + 'h') 2
fmt <
Traceback (most recent call last):
File "C:\Users\maxime.vast\Desktop\Test Campaign Template\Test Suite\Include\readLecroyTRCFile.py", line 143, in <module>
read_timetrace("C:\Users\maxime.vast\Desktop\Test Campaign Template\Test Suite\Traces\KL.ES.001.001.trc")
File "C:\Users\maxime.vast\Desktop\Test Campaign Template\Test Suite\Include\readLecroyTRCFile.py", line 60, in read_timetrace
WAVE_ARRAY_1 = ReadLong(fid, fmt, aWAVE_ARRAY_1)
File "C:\Users\maxime.vast\Desktop\Test Campaign Template\Test Suite\Include\readLecroyTRCFile.py", line 104, in ReadLong
s = unpack(fmt + 'l', s)
struct.error: unpack requires a string argument of length 4
[Finished in 0.2s]
FWIW,你应该使用read(2)
,而不是readline(2)
。 如果fmt
字符串确实是'>'
那么你不应该得到那个错误。 这是一个按预期执行的简短演示。
from struct import unpack
fname = 'qbytes'
#Create a file of all byte values
with open(fname, 'wb') as f:
f.write(bytearray(range(256)))
def ReadWord(fid, fmt, addr):
fid.seek(addr)
s = fid.read(2)
s = unpack(fmt + 'h', s)
return s[0]
fid = open(fname, 'rb')
for i in range(16):
addr = i
n = 256*i + i+1
#Interpret file data as big-endian
print i, ReadWord(fid, '>', addr), n
fid.close()
产量
0 1 1
1 258 258
2 515 515
3 772 772
4 1029 1029
5 1286 1286
6 1543 1543
7 1800 1800
8 2057 2057
9 2314 2314
10 2571 2571
11 2828 2828
12 3085 3085
13 3342 3342
14 3599 3599
15 3856 3856
顺便说一句, struct.unpack()
总是返回一个元组,即使返回值是单个项目。
在二进制文件上使用readline(2)
可能会产生意外结果。 在上面代码的测试文件中,文件中有一个(Linux风格的)换行符\\xa0
。 因此,如果你将s = fid.read(2)
更改为s = fid.readline(2)
一切都可以正常工作,但是在第10行它会崩溃,因为它只读取一个字节,因为该换行符:
from struct import unpack
fname = 'qbytes'
#Create a file of all byte values
with open(fname, 'wb') as f:
f.write(bytearray(range(256)))
def ReadWord(fid, fmt, addr):
fid.seek(addr)
s = fid.readline(2)
print repr(s),
s = unpack(fmt + 'h', s)
return s[0]
with open(fname, 'rb') as fid:
for i in range(16):
addr = i
n = 256*i + i+1
#Interpret file data as big-endian
print i, ReadWord(fid, '>', addr), n
产量
0 '\x00\x01' 1 1
1 '\x01\x02' 258 258
2 '\x02\x03' 515 515
3 '\x03\x04' 772 772
4 '\x04\x05' 1029 1029
5 '\x05\x06' 1286 1286
6 '\x06\x07' 1543 1543
7 '\x07\x08' 1800 1800
8 '\x08\t' 2057 2057
9 '\t\n' 2314 2314
10 '\n'
Traceback (most recent call last):
File "./qtest.py", line 30, in <module>
print i, ReadWord(fid, '>', addr), n
File "./qtest.py", line 22, in ReadWord
s = unpack(fmt + 'h', s)
struct.error: unpack requires a string argument of length 2
您的代码中有几个函数几乎可以执行相同的操作。 这打破了DRY原则:不要重复自己。 这是使用部分功能应用程序解决这个问题的一种方法。 有关详细信息,请参阅functools文档 。
from functools import partial
def ReadNumber(fid, datalen=1, fmt='>', conv='b', addr=0):
fid.seek(addr)
s = fid.read(datalen)
if len(s) != datalen:
raise IOError('Read %d bytes but expected %d at %d' % (len(s), datalen, addr))
return unpack(fmt+conv, s)[0]
ReadByte = partial(ReadNumber, datalen=1, conv='b')
ReadWord = partial(ReadNumber, datalen=2, conv='h')
ReadLong = partial(ReadNumber, datalen=4, conv='l')
ReadFloat = partial(ReadNumber, datalen=4, conv='f')
ReadDouble = partial(ReadNumber, datalen=8, conv='d')
您需要使用关键字来调用这些新功能。 例如,
ReadLong(fid, fmt='>', addr=addr)
没错,这有点啰嗦,但它使代码更具可读性。
格式的长度本身并不重要。 重要的是你在那里指定什么样的格式。 例如,格式规范指定一个字节或甚至八个字节。 所以它真的取决于s
应该有多少个字符的格式。
例如:
>>> struct.unpack('b', 'A')
(65,)
>>> struct.unpack('L', 'A')
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
struct.unpack('L', 'A')
error: unpack requires a string argument of length 4
>>> struct.unpack('L', 'AAAA')
(1094795585,)
如果fmt
真的>
正如你所说,那么它应该工作正常:
>>> struct.unpack('>h', 'AA')
(16705,)
所以,我认为出现错误时, fmt
不只是>
,但别的东西会消耗额外的2个字节。 在unpack
之前尝试打印fmt
。
由于len(fmt)
= 1,这意味着fmt
具有价值。 如果fmt
='h',则fmt+'h'
将为'hh'。 因此,unpack()将需要4个字节的数据,因为每个'h'需要一个短整数(2个字节)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.