Python的struct和格式化字符怎么用
本篇内容介绍了“Python的struct和格式化字符怎么用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
简介文件的存储内容有两种方式,一种是二进制,一种是文本的形式。如果是以文本的形式存储在文件中,那么从文件中读取的时候就会遇到一个将文本转换为Python中数据类型的问题。实际上即使是文本的形式存储,存储的数据也是也是有结构的,因为Python底层是用C来编写的,这里我们也称之为C结构。
Lib/struct.py 就是负责进行这种结构转换的模块。
struct中的方法先看下struct的定义:
__all__=[#Functions'calcsize','pack','pack_into','unpack','unpack_from','iter_unpack',#Classes'Struct',#Exceptions'error']
其中有6个方法,1个异常。
我们主要来看这6个方法的使用:
这些方法主要就是打包和解包的操作,其中一个非常重要的参数就是format,也被成为格式字符串,它指定了每个字符串被打包的格式。
格式字符串格式字符串是用来在打包和解包数据时指定数据格式的机制。 它们使用指定被打包/解包数据类型的 格式字符 进行构建。 此外,还有一些特殊字符用来控制 字节顺序,大小和对齐方式。
字节顺序,大小和对齐方式默认情况下,C类型以机器的本机格式和字节顺序表示,并在必要时通过填充字节进行正确对齐(根据C编译器使用的规则)。
我们也可以手动指定格式字符串的字节顺序,大小和对齐方式:
大端和小端是两种数据存储方式。
第一种Big Endian将高位的字节存储在起始地址
第二种Little Endian将地位的字节存储在起始地址
其实Big Endian更加符合人类的读写习惯,而Little Endian更加符合机器的读写习惯。
目前主流的两大CPU阵营中,PowerPC系列采用big endian方式存储数据,而x86系列则采用little endian方式存储数据。
如果不同的CPU架构直接进行通信,就由可能因为读取顺序的不同而产生问题。
格式字符填充只会在连续结构成员之间自动添加。 填充不会添加到已编码结构的开头和末尾。
当使用非原字节大小和对齐方式即 '<', '>', '=', and '!' 时不会添加任何填充。
我们来看下字符都有哪些格式:
举个例子,比如我们要打包一个int对象,我们可以这样写:
In[101]:fromstructimport*In[102]:pack('i',10)Out[102]:b'\n\x00\x00\x00'In[103]:unpack('i',b'\n\x00\x00\x00')Out[103]:(10,)In[105]:calcsize('i')Out[105]:4
上面的例子中,我们打包了一个int对象10,然后又对其解包。并且计算了 i 这个格式的长度为4字节。
大家可以看到输出结果是 b'\n\x00\x00\x00' ,这里不去深究这个输出到底是什么意思,开头的b表示的是byte,后面是byte的编码。
格式字符之前可以带有整数重复计数。 例如,格式字符串 '4h' 的含义与 'hhhh' 完全相同。
看下如何打包4个short类型:
In[106]:pack('4h',2,3,4,5)Out[106]:b'\x02\x00\x03\x00\x04\x00\x05\x00'In[107]:unpack('4h',b'\x02\x00\x03\x00\x04\x00\x05\x00')Out[107]:(2,3,4,5)
格式之间的空白字符会被忽略,但如果是struct.calcsize 方法的话格式字符中不可有空白字符。
当使用某一种整数格式 ('b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q') 打包值 x 时,如果 x 在该格式的有效范围之外则将引发 struct.error。
格式字符除了数字之外,最常用的就是字符和字符串了。
我们先看下怎么使用格式字符,因为字符的长度是1个字节,我们需要这样做:
In[109]:pack('4c',b'a',b'b',b'c',b'd')Out[109]:b'abcd'In[110]:unpack('4c',b'abcd')Out[110]:(b'a',b'b',b'c',b'd')In[111]:calcsize('4c')Out[111]:4
字符前面的b,表示这是一个字符,否则将会被当做字符串。
格式字符串再看下字符串的格式:
In[114]:pack('4s',b'abcd')Out[114]:b'abcd'In[115]:unpack('4s',b'abcd')Out[115]:(b'abcd',)In[116]:calcsize('4s')Out[116]:4In[117]:calcsize('s')Out[117]:1
可以看到对于字符串来说calcsize返回的是字节的长度。
填充的影响格式字符的顺序可能对大小产生影响,因为满足对齐要求所需的填充是不同的:
>>>pack('ci',b'*',0x12131415)b'*\x00\x00\x00\x12\x13\x14\x15'>>>pack('ic',0x12131415,b'*')b'\x12\x13\x14\x15*'>>>calcsize('ci')8>>>calcsize('ic')5
下面的例子我们将会展示如何手动影响填充效果:
In[120]:pack('llh',1,2,3)Out[120]:b'\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00'
上面的例子中,我们打包1,2,3这三个数字,但是格式不一样,分别是long,long,short。
因为long是4个字节,short是2个字节,所以本质上是不对齐的。
如果想要对齐,我们可以在后面再加上 0l 表示0个long,从而进行手动填充:
In[118]:pack('llh0l',1,2,3)Out[118]:b'\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00'In[122]:unpack('llh0l',b'\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00')Out[122]:(1,2,3)复杂应用
最后看一个复杂点的应用,这个应用中直接从unpack出来的数据读取到元组中:
>>>record=b'raymond\x32\x12\x08\x01\x08'>>>name,serialnum,school,gradelevel=unpack('<10sHHb',record)>>>fromcollectionsimportnamedtuple>>>Student=namedtuple('Student','nameserialnumschoolgradelevel')>>>Student._make(unpack('<10sHHb',record))Student(name=b'raymond',serialnum=4658,school=264,gradelevel=8)
“Python的struct和格式化字符怎么用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。