Python中缺少类似C语言structs这样直接对字节序列进行序列化和反序列化的语法,作为一门脚本语言这是不必要的,但作为一门完整的编程语言必须提供这样的能力,否则不能独立的处理二进制文件和数据流。struct模块即为处理这类问题而诞生。

要处理字节序需要三个能力:首先是字节和变量值的互相转化,其次是字节序序问题,最后是数据对其的处理。

python中的基本变量类型有限,分别为int,float,bool类型。并且根据不同的运行环境所占用的长度不确定,这点跟C语言完全没法比。因此模块中我们需要提供一个确定变量和字节长度的转换方法,也就是struct模块中的 Format Characters。还有字节序的问题,Inter x86 和AMD64 系列主机都是小尾数,而网络字节序是大尾数的字节序,并且有时我们要处理一份二进制文件事先并不知道其是大尾数还是小尾数表示,这些都需要开发人员去指定,因此需要提供对字节序的控制,在struct中也有对应的处理 Byte Order。 最后就是数据对其的处理,我们知道C语言中为了更有效的处理struct类型会进行对其处理,例如结构体 Student代码如下,如果按照基本类型计算 一个char占用一个字节,两个int共占用8个自己,应该是9个字节的长度,但实际占用了12个字节。C编译器在处理如下结构体时一般按4字节对齐,这样在gender和class_id之间会有3个字节用于对齐。

struct Student{

char gender;

int class_id;

int age;

};

int main(int argc, const char * argv[]) {

// insert code here...

printf("length of int %ld\n",sizeof(int));

printf("length of Student %ld\n",sizeof(Student));

return 0;

}

>> output

length of int 4

length of Student 12

struct 模块中将对其与字节序控制结合在一起,通过结构化字符串的首字符控制,如下:

字符

字节序

是否sizeof对其

@

本机

=

本机

>

小尾数

<

大尾数

!

网络字节序(大尾数)

@ 是默认字符,如果结构化字符串没有字节序控制符则默认为@。

接下来看变量和字节转换控制符有哪些:

符号

C 类型

Python 类型

字节长度

x

对其位

-

-

c

char

长度为1的 bytes 字符串

1

b

signed char

int

1

B

unsigned char

int

1

?

_Bool

bool

1

h

short

int

2

H

unsigned short

int

2

i

int

int

4

I

unsigned int

int

4

l

long

int

4

L

unsigned long

int

4

q

long long

int

4

Q

unsigned long long

int

4

n

ssize_t

int

-

N

size_t

int

-

e

半精度浮点数(c不支持)

float

2

f

float

float

4

d

double

float

8

s

char[]

bytes

-

p

char[]

bytes

-

P

void *

bytes

-

struct通过格式化字符串将字节和变量互转,格式化字符串由上述的字节序字符+格式化字符组成,且字节序字符可省略。例如: >hhl 表示两个short 和一个long。

>>> from struct import *

>>> pack('>hhl', 1, 2, 3)

b'\x00\x01\x00\x02\x00\x00\x00\x03'

>>> unpack('>hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03')

(1, 2, 3)

连续的格式化字符可以通过数字简写,>hhl完全等价与 >2hl。

上例中pack和unpack是struct模块中的两个方法,分别表示将变量值转换为二进制字符串和从二进制字符串中转换出变量值。在struct模块中有4个基本的转换函数、一个批量转换的迭代器方法和一个计算长度的函数:

struct.pack(format, v1, v2, ...) # 打包

struct.pack_into(format, buffer, offset, v1, v2, ...)

struct.unpack(format, buffer) # 解码

struct.unpack_from(format, buffer, offset=0)

如上4个基本转换函数,其中pack和unpack是一对,pack将v1,v2的值按照format的格式转化为二进制字符串,unpack将二进制字符串buffer按照format的格式转换一元组。pack_into和unpack_into是一对,pack_into将v1,v2的值转换成的二进制依次放入buffer中offset开始的位置。unpack_into则从buffer的offset开始转换出变量值。

struct.calcsize(format)

calcsize方法类似于C语言中sizeof(Struct) 用于计算format具体占用多少字符。

struct.iter_unpack(format, buffer)

iter_unpack以迭代方式转换buffer中的字节,每次都会读取并转化calcsize(format)长度的字节。

以上都是对struct模块中功能的介绍,为了更清楚的看怎么使用,还是需要例子。

1、使用基础的pack/unpack打包三个int型变量

>>> from struct import *

>>> pack('>hhl', 1, 2, 3)

b'\x00\x01\x00\x02\x00\x00\x00\x03'

>>> unpack('>hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03')

(1, 2, 3)

>>> calcsize('hhl')

8

上述代码与官网代码中format字符串不同,加了个>符号,因为在mac操作系统python 2.7 的环境中c编译的long占用8个字节因此l长度为8。整个结果并按住8位对其,pack结果为:'\x01\x00\x02\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00'。

2、unpack 的结果可以直接通过变量接受,也可以使用命名元组。

>>> record = b'raymond \x32\x12\x08\x01\x08'

>>> name, serialnum, school, gradelevel = unpack('<10sHHb', record)

>>> from collections import namedtuple

>>> Student = namedtuple('Student', 'name serialnum school gradelevel')

>>> Student._make(unpack('<10sHHb', record))

Student(name=b'raymond ', serialnum=4658, school=264, gradelevel=8)

3、由于对其的原因,格式化字符的位置可能影响结构化的长度。

>>> 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

struct 模块不会对末尾的字符对其,如上c表示一个字节,在C语言中一个结构体不论先写int还是char最终长度都为8,但是struct模块中不同。如果想要结尾的字符也对其,需要用接下来的方法。

4、结尾使用 0 + 格式化字符的方式来结尾对其

>>> pack('llh', 1, 2, 3)

b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00'

>>> pack('llh0l', 1, 2, 3)

b'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00'

格式字符串llh最后的h占用2位,而格式字符串llh0l共占用12位

5、数字 + c和数字 + s的区别

>>> scbytes = b'abcde'

>>> unpack('5s',scbytes)

(b'abcde',)

>>> unpack('5c',scbytes)

(b'a', b'b', b'c', b'd', b'e')

>>>

可见 数字+c的方式解码出5个长度为1的字符串,而数字+s的方式解码出长度为5的一个字符串

除了直接使用函数的方式打包和解码,struct模块也支持使用类的方式。类定义如下:

class struct.Struct(format)

pack(v1, v2, ...)

pack_into(buffer, offset, v1, v2, ...)

unpack(buffer)

unpack_from(buffer, offset=0)

iter_unpack(buffer)

format

size

类定义包含五个方法和两个属性,其中五个方法与模块中的方法一致。而size属性则是calcsize方法的体现。

>>> record=b'raymond \x32\x12\x08\x01\x08'

>>> ray = Struct('<10sHHb')

>>> ray.unpack(record)

(b'raymond ', 4658, 264, 8)

>>> ray.pack(b'raymond ', 4658, 264, 8)

b'raymond 2\x12\x08\x01\x08'

python序列化模块struct_python的struct模块相关推荐

  1. python学习day32 黏包 struct模块

    为什么会出现黏包问题?  首先只有在TCP协议中才会出现黏包现象 是因为TCP协议是面向流的协议 在发送的数据 传输过程中 有缓存机制 来避免数据丢失 因此 在连续发送小数据的时候 以及接收大小不符的 ...

  2. python tcp黏包和struct模块解决方法,大文件传输方法及MD5校验

    https://www.cnblogs.com/zaizai1573/p/10230973.html 一.TCP协议 粘包现象 和解决方案 黏包现象 让我们基于tcp先制作一个远程执行命令的程序(命令 ...

  3. python中struct_Python的Struct模块,用法以及个人理解

    简介 python strtuct模块主要在Python中的值于C语言结构之间的转换.可用于处理存储在文件或网络连接(或其它来源)中的二进制数据. 顺序.格式字符 现在先不要看图表,稍后我们回来看.图 ...

  4. python 二进制流_Python中对字节流/二进制流的操作:struct模块简易使用教程

    前言 前段时间使用Python解析IDX文件格式的MNIST数据集,需要对二进制文件进行读取操作,其中我使用的是struct模块.查了网上挺多教程都写的挺好的,不过对新手不是很友好,所以我重新整理了一 ...

  5. python把文件读成字节流_Python中struct模块对字节流/二进制流的操作教程

    前言 最近使用Python解析IDX文件格式的MNIST数据集,需要对二进制文件进行读取操作,其中我使用的是struct模块.查了网上挺多教程都写的挺好的,不过对新手不是很友好,所以我重新整理了一些笔 ...

  6. python中的struct模块

    struct模块用于二进制和结构体之间的互相转化,此模块中大部分函数接受一个实现了Buffer协议的对象,最常见的实现了Buffer协议的对象包括bytes.bytearray等,大多数像byte数组 ...

  7. python struct模块_python struct 模块

    struct模块用于二进制和结构体之间的互相转化,此模块中大部分函数接受一个实现了Buffer协议的对象,最常见的实现了Buffer协议的对象包括bytes.bytearray等,大多数像byte数组 ...

  8. python序列化模块struct_Python进阶-XII serialize(序列化)、序列化模块

    一.serialize 序列化 1.什么叫序列化--将原本的字典.列表等内容转换成一个字符串的过程就叫做序列化. 比如,我们在python代码中计算的一个数据需要给另外一段程序使用,那我们怎么给? 现 ...

  9. python的功能模块_Python的功能模块[1] - struct - struct 在网络编程中的使用

    struct模块/ struct Module 在网络编程中,利用 socket 进行通信时,常常会用到 struct 模块,在网络通信中,大多数传递的数据以二进制流(binary data)存在.传 ...

最新文章

  1. 系统性能优化 1-1 Redis删除key和字符串拼接
  2. 常用的前端辅助开发工具有哪些
  3. Csharp: Treeview check list value
  4. python utc 时间
  5. Zdenek Kalal的TLD Tracker(牛啊,学习!)
  6. python bokeh_浅谈python可视化包Bokeh
  7. 机器学习算法思想简单梳理
  8. 大数据分析如何应用在驾驶世界
  9. android 蓝牙 发送字符串,Android向TLSR8266蓝牙mesh发送指令
  10. 2014年世界互联网大会最值得分享的PPT:互联网思维
  11. ubuntu18.04 HP笔记本合上盖子不休眠不断网
  12. Go简明语法汇总--入门
  13. ICV:预计到2026年,全球乘用车单车将平均配置3.8颗摄像头
  14. 计算机专业surface pro,surface pro4家庭版和专业版的不同
  15. 与外国教授用email交流
  16. activiti完整教程
  17. android 系统图片为壁纸后,壁纸拉伸的现象
  18. html转docx文档
  19. 计算机教室安全排查,微机室安全检查制度
  20. 【数据分析】电商平台数据分析

热门文章

  1. [云炬ThinkPython阅读笔记]2.9 术语表
  2. 学长毕业日记 :本科毕业论文写成博士论文的神操作20170316
  3. 吴恩达《优化深度神经网络》精炼笔记(1)-- 深度学习的实用层面
  4. SQL中的三大常用字符
  5. android 中intent跳转是灰色的,没有效果,显示intent = null
  6. 关于 Intel 8253/8254
  7. 【❗JS奇技淫巧❗】JavaScript:截取DataURL中的base64字符串
  8. java自定义注解解析及自定义注解
  9. ACM/ICPC 2018亚洲区预选赛北京赛站网络赛 80 Days(双向队列+尺取法)
  10. zcmu-1957(状态压缩枚举)