Python struct模块核心用法与字节序详解
本文深入解析Python内建模块struct,解决高级语言与底层字节流交互问题。详细讲解struct.pack、unpack及calcsize三大核心函数,结合大小端字节序实例,演示整数、字符串等类型的打包与解包过程,帮助开发者掌握跨语言数据交互的关键技术。
本文重点探讨Python内置模块struct的具体应用与原理。
在Python中,变量类型主要涵盖列表、元组、字典和集合等高级抽象结构,并不像C语言那样直接定义位、字节或整型等底层基础类型。由于Python属于高级解释型语言,其代码在执行前需经过翻译处理。为了消除Python与其他编程语言在类型定义上的差异,Python提供的内建模块struct能够有效解决这一类型转换障碍。
相关基础知识介绍:
在struct模块中,最核心的三个功能如下:
(1)struct.pack:依据指定的格式符,将Python的值转换为字符串对象。需要注意的是,Python原生没有字节(Byte)类型,因此这里的字符串可视为字节流或字节数组。 (2)struct.unpack:功能与struct.pack相反,用于将字节流还原为Python数据类型,该函数执行后返回一个元组。 (3)struct.calcsize:用于计算格式字符串所对应结果所占用的长度。
在数据转换过程中涉及的格式操作说明:
| 格式符 | C语言类型 | Python类型 |
|---|---|---|
| x | pad byte | no value |
| c | char | string of length 1 |
| b | signed char | integer |
| B | unsigned char | integer |
| ? | _Bool | bool |
| h | short | integer |
| H | unsigned short | integer |
| i | int | integer |
| I | unsigned int | integer or long |
| l | long | integer |
| L | unsigned long | long |
| q | long long | long |
| Q | unsigned long long | long |
| f | float | float |
| d | double | float |
| s | char[] | string |
| p | char[] | string |
| P | void * | long |
具体实例分析:
#!/usr/bin/python
# -*- coding:utf-8 -*-
'''测试struct模块'''
from struct import *
import array
def fun_calcsize():
print 'ci:',calcsize('ci')#计算格式占内存大小
print '@ci:',calcsize('@ci')
print '=ci:',calcsize('=ci')
print '>ci:',calcsize('>ci')
print '<ci:',calcsize('<ci')
print 'ic:',calcsize('ic')#计算格式占内存大小
print '@ic:',calcsize('@ic')
print '=ic:',calcsize('=ic')
print '>ic:',calcsize('>ic')
print '<ic:',calcsize('<ic')
def fun_pack(Format,msg = [0x11223344,0x55667788]):
result = pack(Format,*msg)
print 'pack'.ljust(10),str(type(result)).ljust(20),
for i in result:
print hex(ord(i)), # ord把ASCII码表中的字符转换成对应的整形,hex将数值转化为十六进制
print
result = unpack(Format,result)
print 'unpack'.ljust(10),str(type(result)).ljust(20),
for i in result:
print hex(i),
print
def fun_pack_into(Format,msg = [0x11223344,0x55667788]):
r = array.array('c',' '*8)#大小为8的可变缓冲区,writable buffer
result = pack_into(Format,r,0,*msg)
print 'pack_into'.ljust(10),str(type(result)).ljust(20),
for i in r.tostring():
print hex(ord(i)),
print
result = unpack_from(Format,r,0)
print 'pack_from'.ljust(10),str(type(result)).ljust(20),
for i in result:
print hex(i),
print
def IsBig_Endian():
'''判断本机为大/小端'''
a = 0x12345678
result = pack('i',a)#此时result就是一个string字符串,字符串按字节同a的二进制存储内容相同。
if hex(ord(result[0])) == '0x78':
print '本机为小端'
else:
print '本机为大端'
def test():
a = '1234'
for i in a:
print '字符%s的二进制:'%i,hex(ord(i))#字符对应ascii码表中对应整数的十六进制
'''
不用unpack()返回的数据也是可以使用pack()函数的,只要解包的字符串符合解包格式即可,
pack()会按照解包格式将字符串在内存中的二进制重新解释(说的感觉不太好...,见下例)
'''
print '大端:',hex(unpack('>i',a)[0])#因为pack返回的是元组,即使只有一个元素也是元组的形式
print '小端:',hex(unpack('<i',a)[0])
if __name__ == "__main__":
print '判断本机是否为大小端?',
IsBig_Endian()
fun_calcsize()
print '大端:'
Format = ">ii"
fun_pack(Format)
fun_pack_into(Format)
print '小端:'
Format = "<ii"
fun_pack(Format)
fun_pack_into(Format)
print 'test'
test()
'''
result:
判断本机是否为大小端? 本机为小端
ci: 8
@ci: 8
=ci: 5
>ci: 5
<ci: 5
ic: 5
@ic: 5
=ic: 5
>ic: 5
<ic: 5
大端:
pack <type 'str'> 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88
unpack <type 'tuple'> 0x11223344 0x55667788
pack_into <type 'NoneType'> 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88
pack_from <type 'tuple'> 0x11223344 0x55667788
小端:
pack <type 'str'> 0x44 0x33 0x22 0x11 0x88 0x77 0x66 0x55
unpack <type 'tuple'> 0x11223344 0x55667788
pack_into <type 'NoneType'> 0x44 0x33 0x22 0x11 0x88 0x77 0x66 0x55
pack_from <type 'tuple'> 0x11223344 0x55667788
test
字符1的二进制: 0x31
字符2的二进制: 0x32
字符3的二进制: 0x33
字符4的二进制: 0x34
大端:0x31323334
小端:0x34333231
'''
本实例运行的Python软件环境配置为:Windows 10系统,Anaconda3集成环境,PyCharm编辑器,Python版本为3.6。
总结
以上是关于Python内建模块struct的完整实例解析,希望能为读者提供实际帮助。感兴趣的用户可继续查阅本站其他相关专题内容。如有疏漏之处,欢迎留言指正,感谢大家的支持!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









