python的struct模块

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字节对齐,这样在genderclass_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
上例中packunpack是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个基本转换函数,其中packunpack是一对,packv1v2的值按照format的格式转化为二进制字符串,unpack将二进制字符串buffer按照format的格式转换一元组。pack_intounpack_into是一对,pack_intov1v2的值转换成的二进制依次放入bufferoffset开始的位置。unpack_into则从bufferoffset开始转换出变量值。

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'

原文地址:https://www.cnblogs.com/fog2012/p/11069972.html

时间: 2024-10-14 01:26:17

python的struct模块的相关文章

python中struct模块及packet和unpacket

转自:http://www.cnblogs.com/gala/archive/2011/09/22/2184801.html 我们知道python只定义了6种数据类型,字符串,整数,浮点数,列表,元组,字典.但是C语言中有些字节型的变量,在python中该如何实现呢?这点颇为重要,特别是要在网络上进行数据传输的话. 有的时候需要用python处理二进制数据,比如,存取文件,socket操作时.这时候,可以使用python的struct模块来完成.可以用 struct来处理c语言中的结构体. st

Python学习——struct模块的pack unpack示例

import struct pack.unpack.pack_into.unpack_from # ref: http://blog.csdn.net/JGood/archive/2009/06/22/4290158.aspx import struct #pack - unpack print print '===== pack - unpack =====' str = struct.pack("ii", 20, 400) print 'str:', str print 'len(

python中struct模块

转:  http://www.cnblogs.com/coser/archive/2011/12/17/2291160.html 最近在学习python网络编程这一块,在写简单的socket通信代码时,遇到了struct这个模块的使用,当时不太清楚这到底有和作用,后来查阅了相关资料大概了解了,在这里做一下简单的总结. 了解c语言的人,一定会知道struct结构体在c语言中的作用,它定义了一种结构,里面包含不同类型的数据(int,char,bool等等),方便对 某一结构对象进行处理.而在网络通信

Python:struct模块的pack、unpack

mport struct pack.unpack.pack_into.unpack_from 1 # ref: http://blog.csdn<a href="http://lib.csdn.net/base/dotnet" class='replace_word' title=".NET知识库" target='_blank' style='color:#df3434; font-weight:bold;'>.NET</a>/JGood/

Python使用struct处理二进制

有的时候需要用python处理二进制数据,比如,存取文件,socket操作时.这时候,可以使用python的struct模块来完成.可以用 struct来处理c语言中的结构体. struct模块中最重要的三个函数是pack(), unpack(), calcsize() pack(fmt, v1, v2, ...)     按照给定的格式(fmt),把数据封装成字符串(实际上是类似于c结构体的字节流) unpack(fmt, string)       按照给定的格式(fmt)解析字节流stri

Python使用struct处理二进制(转载)

有的时候需要用python处理二进制数据,比如,存取文件,socket操作时.这时候,可以使用python的struct模块来完成.可以用 struct来处理c语言中的结构体. struct模块中最重要的三个函数是pack(), unpack(), calcsize() pack(fmt, v1, v2, ...)     按照给定的格式(fmt),把数据封装成字符串(实际上是类似于c结构体的字节流) unpack(fmt, string)       按照给定的格式(fmt)解析字节流stri

python 中 struct 用法

下面就介绍这个模块中的几个方法. struct.pack():我的理解是,python利用 struct模块将字符(比如说 int,long ,unsized int 等)拆成 字节流(用十六进制表示),便于传输. 其函数原型为:struct.pack(fmt, v1, v2, ...),fmt表示的是类型,后面的V1 V2..参数有多少,那么对应的类型数量就有多少. >>> import struct >>> x=10 >>> y=20 >&g

Python采用struct处理二进制

有时需要使用python二进制数据,实例,件.socket操作时.这时候.能够使用python的struct模块来完毕.能够用 struct来处理c语言中的结构体. struct模块中最重要的三个函数是pack(), unpack(), calcsize() pack(fmt, v1, v2, ...)     依照给定的格式(fmt),把数据封装成字符串(实际上是类似于c结构体的字节流) unpack(fmt, string)       依照给定的格式(fmt)解析字节流string,返回解

Python使用struct处理二进制(pack和unpack用法)

转载自:http://www.cnblogs.com/gala/archive/2011/09/22/2184801.html 这篇文章写的很好,所以无耻的转了.. 有的时候需要用python处理二进制数据,比如,存取文件,socket操作时.这时候,可以使用python的struct模块来完成.可以用 struct来处理c语言中的结构体. struct模块中最重要的三个函数是pack(), unpack(), calcsize() ? # 四号程序员 http://www.coder4.com