struct模块提供了用于在字节字符串和Python原生数据类型之间转换函数,比如数字和字符串。

Python版本: 2.x & 3.x

  该模块作用是完成Python数值和C语言结构体的Python字符串形式间的转换。

这可以用于处理存储在文件中或从网络连接中存储的二进制数据,以及其他数据源。

1. 模块函数和Struct类

  它除了提供一个Struct类之外,还有许多模块级的函数用于处理结构化的值。这里有个格式符(Format specifiers)的概念,是指从字符串格式转换为已编译的表示形式,类似于正则表达式的处理方式。通常实例化Struct类,调用类方法来完成转换,比直接调用模块函数有效的多。下面的例子都是使用Struct类。

2. Packing(打包)和Unpacking(解包)

  Struct支持将数据packing(打包)成字符串,并能从字符串中逆向unpacking(解压)出数据。

  在本例中,格式指定器(specifier)需要一个整型或长整型,一个两个字节的string,和一个浮点数。格式符中的空格用于分隔各个指示器(indicators),在编译格式时会被忽略。

import struct

import binascii

values = (1, 'ab'.encode('utf-8'), 2.7)
s = struct.Struct('I 2s f')
packed_data = s.pack(*values) print('原始值:', values)
print('格式符:', s.format)
print('占用字节:', s.size)
print('打包结果:', binascii.hexlify(packed_data))

# output
原始值: (1, b'ab', 2.7)
格式符: b'I 2s f'
占用字节: 12
打包结果: b'0100000061620000cdcc2c40'

  这个示例将打包的值转换为十六进制字节序列,用binascii.hexlify()方法打印出来。

  使用unpack()方法解包。

import struct
import binascii packed_data = binascii.unhexlify(b'0100000061620000cdcc2c40') s = struct.Struct('I 2s f')
unpacked_data = s.unpack(packed_data)
print('解包结果:', unpacked_data)

# output
解包结果: (1, b'ab', 2.700000047683716)

  将打包的值传给unpack(),基本上返回相同的值(浮点数会有差异)。

3. 字节顺序/大小/对齐

  默认情况下,pack是使用本地C库的字节顺序来编码的。格式化字符串的第一个字符可以用来表示填充数据的字节顺序、大小和对齐方式,如下表所描述的:

Character Byte order Size Alignment
@ 本地 本地 本地
= 本地 standard none
< little-endian(小字节序) standard none
> big-endian(大字节序) standard none
! network (= big-endian) standard none

  如果格式符中没有设置这些,那么默认将使用 @。

  本地字节顺序是指字节顺序是由当前主机系统决定。比如:Intel x86和AMD64(x86-64)使用小字节序; Motorola 68000和 PowerPC G5使用大字节序。ARM和Intel安腾支持切换字节序。可以使用sys.byteorder查看当前系统的字节顺序。

  本地大小(Size)和对齐(Alignment)是由c编译器的sizeof表达式确定的。它与本地字节顺序对应。

  标准大小由格式符确定,下面会讲各个格式的标准大小。

示例:

import struct
import binascii values = (1, 'ab'.encode('utf-8'), 2.7)
print('原始值 : ', values) endianness = [
('@', 'native, native'),
('=', 'native, standard'),
('<', 'little-endian'),
('>', 'big-endian'),
('!', 'network'),
] for code, name in endianness:
s = struct.Struct(code + ' I 2s f')
packed_data = s.pack(*values)
print()
print('格式符 : ', s.format, 'for', name)
print('占用字节: ', s.size)
print('打包结果: ', binascii.hexlify(packed_data))
print('解包结果: ', s.unpack(packed_data))

# output
原始值 : (1, b'ab', 2.7) 格式符 : b'@ I 2s f' for native, native
占用字节: 12
打包结果: b'0100000061620000cdcc2c40'
解包结果: (1, b'ab', 2.700000047683716) 格式符 : b'= I 2s f' for native, standard
占用字节: 10
打包结果: b'010000006162cdcc2c40'
解包结果: (1, b'ab', 2.700000047683716) 格式符 : b'< I 2s f' for little-endian
占用字节: 10
打包结果: b'010000006162cdcc2c40'
解包结果: (1, b'ab', 2.700000047683716) 格式符 : b'> I 2s f' for big-endian
占用字节: 10
打包结果: b'000000016162402ccccd'
解包结果: (1, b'ab', 2.700000047683716) 格式符 : b'! I 2s f' for network
占用字节: 10
打包结果: b'000000016162402ccccd'
解包结果: (1, b'ab', 2.700000047683716)

4. 格式符

格式符对照表如下:

Format C Type Python type Standard size Notes
x pad byte no value
c char bytes of length 1 1
b signed char integer 1 (1),(3)
B unsigned char integer 1 (3)
? _Bool bool 1 (1)
h short integer 2 (3)
H unsigned short integer 2 (3)
i int integer 4 (3)
I unsigned int integer 4 (3)
l long integer 4 (3)
L unsigned long integer 4 (3)
q long long integer 8 (2), (3)
Q unsigned long long integer 8 (2), (3)
n ssize_t integer (4)
N size_t integer (4)
f float float 4 (5)
d double float 8 (5)
s char[] bytes
p char[] bytes
P void * integer (6)

5. 缓冲区

  将数据打包成二进制通常是用在对性能要求很高的场景。

在这类场景中可以通过避免为每个打包结构分配新缓冲区的开销来优化。

pack_into()和unpack_from()方法支持直接写入预先分配的缓冲区。

import array
import binascii
import ctypes
import struct s = struct.Struct('I 2s f')
values = (1, 'ab'.encode('utf-8'), 2.7)
print('原始值:', values) print()
print('使用ctypes模块string buffer') b = ctypes.create_string_buffer(s.size)
print('原始buffer :', binascii.hexlify(b.raw))
s.pack_into(b, 0, *values)
print('打包结果写入 :', binascii.hexlify(b.raw))
print('解包 :', s.unpack_from(b, 0)) print()
print('使用array模块') a = array.array('b', b'\0' * s.size)
print('原始值 :', binascii.hexlify(a))
s.pack_into(a, 0, *values)
print('打包写入 :', binascii.hexlify(a))
print('解包 :', s.unpack_from(a, 0))

# output
原始值: (1, b'ab', 2.7) 使用ctypes模块string buffer
原始buffer : b'000000000000000000000000'
打包结果写入 : b'0100000061620000cdcc2c40'
解包 : (1, b'ab', 2.700000047683716) 使用array模块
原始值 : b'000000000000000000000000'
打包写入 : b'0100000061620000cdcc2c40'
解包 : (1, b'ab', 2.700000047683716)

首发地址: Python标准库笔记(6) — struct模块

Python标准库笔记(8) — pprint模块的更多相关文章

  1. Python标准库笔记(10) — itertools模块

    itertools 用于更高效地创建迭代器的函数工具. itertools 提供的功能受Clojure,Haskell,APL和SML等函数式编程语言的类似功能的启发.它们的目的是快速有效地使用内存, ...

  2. Python标准库笔记(9) — functools模块

    functools 作用于函数的函数 functools 模块提供用于调整或扩展函数和其他可调用对象的工具,而无需完全重写它们. 装饰器 partial 类是 functools 模块提供的主要工具, ...

  3. Python标准库笔记(11) — Operator模块

    Operator--标准功能性操作符接口. 代码中使用迭代器时,有时必须要为一个简单表达式创建函数.有些情况这些函数可以用一个lambda函数实现,但是对于某些操作,根本没必要去写一个新的函数.因此o ...

  4. Python标准库笔记(6) — struct模块

    该模块作用是完成Python数值和C语言结构体的Python字符串形式间的转换.这可以用于处理存储在文件中或从网络连接中存储的二进制数据,以及其他数据源. 用途: 在Python基本数据类型和二进制数 ...

  5. Python 标准库笔记(1) — String模块

    原文出处: j_hao104 String模块包含大量实用常量和类,以及一些过时的遗留功能,并还可用作字符串操作. 1. 常用方法 常用方法 描述 str.capitalize() 把字符串的首字母大 ...

  6. (转)Python 标准库笔记:string模块

    String模块包含大量实用常量和类,以及一些过时的遗留功能,并还可用作字符串操作. 原文:http://www.10tiao.com/html/384/201709/2651305041/1.htm ...

  7. Python标准库笔记(1) — string模块

    String模块包含大量实用常量和类,以及一些过时的遗留功能,并还可用作字符串操作. 1. 常用方法 常用方法 描述 str.capitalize() 把字符串的首字母大写 str.center(wi ...

  8. Python标准库笔记(4) — collections模块

    这个模块提供几个非常有用的Python容器类型 1.容器 名称 功能描述 OrderedDict 保持了key插入顺序的dict namedtuple 生成可以使用名字来访问元素内容的tuple子类 ...

  9. Python标准库笔记(3) — datetime模块

    datetime模块提供了简单和复杂的方式用于操纵日期和时间的类.虽然支持日期和时间运算,但实现的重点是为了输出格式化和操作高效地提取属性. 1. 模块内容 内容 描述 常量   datetime.M ...

随机推荐

  1. 自定义样式,使用浏览器阅读epub格式的电子书

    epub格式的电子式一般用专门的阅读器打开,但是如果可以使用浏览器打开,就可以随意更改css了,获得极致的体验效果. 比如可以自定义字体.行间距.背景色.字体大小.缩进等等... 当然,如果您不需要添 ...

  2. VS2013 UML 如何复制文件

    如:复制活动图,文件复制了显示不了 正确做法:新建活动图,打开源活动图,全选,复制,在新建的活动图粘贴,以此实现复制

  3. 【BZOJ2724】蒲公英(分块)

    [BZOJ2724]蒲公英(分块) 题面 洛谷 谴责权限题的行为 题解 分块什么的都不会,根本就没写过几次. 复杂度根本不会分析,吓得我赶快来练练. 这题要求的是区间众数,显然没有什么很好的主席树之类 ...

  4. Valid Parentheses - LeetCode

    目录 题目链接 注意点 解法 小结 题目链接 Valid Parentheses - LeetCode 注意点 考虑输入为空的情况 解法 解法一:如果是'('.'{'.'['这三者就入栈,否则就判断栈 ...

  5. 【bzoj4011】 HNOI2015—落忆枫音

    http://www.lydsy.com/JudgeOnline/problem.php?id=4011 (题目链接) 题意 给出一个拓扑图,再加入一条边,问树形图个数. Solution 右转题解→ ...

  6. 使用cmstp绕过应用程序白名单

    默认情况下,AppLocker允许在文件夹中执行二进制文件,这是可以绕过它的主要原因.已经发现,这样的二进制文件可以很容易地用于绕过AppLocker和UAC.与Microsoft相关的二进制文件之一 ...

  7. JVM 垃圾回收机制和常见算法

    垃圾回收机制:释放那些不再持有引用的对象的内存. 如何判断对象是否需要回收? 引用计数:对象,内存,磁盘空间等被引用次数保存起来,次数为0时将其进行释放. 对象引用遍历:对象应用遍历从一组对象开始,沿 ...

  8. python之旅:并发编程之多进程

    一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程.P ...

  9. git<git rebase 修改以前提交过的内容>

      git rebase 使用总结: 使用git rebase 修改以前已经提交的内容 比如要修改之前的commit的 hashcode为:187f869c9d54c9297d6b0b1b4ff47d ...

  10. poj 3685 二分

    Matrix Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 7415   Accepted: 2197 Descriptio ...