当前位置: 首页 > 后端技术 > Python

Python3structerror-argumentfor's'mustbeabytesobject

时间:2023-03-26 14:44:13 Python

在使用python3存储和解析文件打包二进制数据的过程中,使用struct模块运行如下代码时出现错误:F=open('data.bin','wb')importstructdata=struct.pack('>i4sh',7,'spam',8)数据报错信息如下:errorTraceback(mostrecentcalllast)in>1F=open('data.bin','wb')2importstruct---->3data=struct.pack('>i6sh',7,'spam',8)4dataerror:argumentfor's'mustbeabytesobject先说解决方法:格式化字符串的值在python中是bytes类型,而python3中所有文本都是Unicode,所以需要转换成bytes类型,在'spam'前面加上'b'进行转换。F=open('data.bin','wb')importstructdata=struct.pack('>i4sh',7,b'spam',8)数据输出结果为:b'\x00\x00\x00\x07spam\x00\x08'python3新加入的bytes类型,在python2中字节类型和字符类型区别不大,但在python3中最大的特点是对文本和二进制数据做了更明确的区分。文本始终是Unicode,由字符类型表示,而二进制数据由字节类型表示。Python3不会以任何隐式方式混合字节和字符类型,因此字符串和字节包在python3中不能拼接(在python2中可以自动转换),字符串不能在字节包中搜索,也不能将字符串传递到a中函数,其参数是一个字节包。需要注意的是,在网络数据传输过程中,python2可以通过字符串(string)传输,而python3只能通过二进制(bytes)传输,所以传输文本需要进行转换。转换方法:str→byte使用encode()方法byte→str使用decode()方法汉字字符串转二进制:'Hello'.encode('utf-8')输出:b'\xe4\xbd\xa0\xe5\xa5\xbd'二进制转换字符串:b'\xe4\xbd\xa0\xe5\xa5\xbd'.decode('utf-8')输出:'hello'英文字符串转换二进制'helloworld'.encode('utf-8')output:b'helloworld'encode()和decode()方法中默认的编码是utf-8,但是为了避免出错,最好加上编码。只知道加上'b'可以解决问题还是不行,'>i4sh'看不懂,于是去官方文档查了一下struct,看到结果如下:struct.pack(format,v1,v2,...)返回一个bytesObject,其中包含按照格式字符串格式打包的值v1,v2,...。参数的数量必须与格式字符串所需的值完全匹配。可以看出在python中i对应一个整数,s对应一个字符串,h对应一个整数。格式字符前面可以有整数重复计数。例如,格式字符串“4h”与“hhhh”的含义完全相同。所以我测试了它并在h之前添加了数字2:F=open('data.bin','wb')importstructdata=struct.pack('>i4s2h',7,b'spam',8)datareported错误如下:-----------------------------------------------------------------------错误回溯(最近调用最后)1F=open('data.bin','wb')2importstruct---->3data=struct.pack('>i4s2h',7,b'spam',8)4数据错误:packexpected4itemsforpacking(got3)也意味着2h在s之后需要2个整数参数,但是'4s'不需要四个字节参数。对于's'格式字符,计数被解释为以字节为单位的长度,而不是像其他格式字符那样重复计数;例如,'10s'表示10个字节的字节字符串,而'10c'表示10个字符。如果未给出计数,则默认为1。对于打包操作,字节串将被截断或适当地用空字节填充。于是做了个测试,把s前面的数字从1逐渐增加到6,输出结果如下:b'\x00\x00\x00\x07s\x00\x08'#'>i1sh'b'\x00\x00\x00\x07sp\x00\x08'#'>i2sh'b'\x00\x00\x00\x07spa\x00\x08'#'>i3sh'b'\x00\x00\x00\x07spam\x00\x08'#'>i4sh'b'\x00\x00\x00\x07spam\x00\x00\x08'#'>i5sh'b'\x00\x00\x00\x07spam\x00\x00\x00\x08'#'>i6sh'当数字小于后面的字节长度时,将被截取,如果超过长度,则用空字节填充。