Python标准库笔记(8) — pprint模块

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

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

1. 模块函数和Struct类

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

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

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

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

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

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

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

  使用unpack()方法解包。

1import struct 2import binascii 3 4packed_data = binascii.unhexlify(b'0100000061620000cdcc2c40') 5 6s = struct.Struct('I 2s f') 7unpacked_data = s.unpack(packed_data) 8print('解包结果:', unpacked_data)

1# output 2解包结果: (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表达式确定的。它与本地字节顺序对应。

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

示例:

1import struct 2import binascii 3 4values = (1, 'ab'.encode('utf-8'), 2.7) 5print('原始值 : ', values) 6 7endianness = [ 8 ('@', 'native, native'), 9 ('=', 'native, standard'), 10 ('<', 'little-endian'), 11 ('>', 'big-endian'), 12 ('!', 'network'), 13] 14 15for code, name in endianness: 16 s = struct.Struct(code + ' I 2s f') 17 packed_data = s.pack(*values) 18 print() 19 print('格式符 : ', s.format, 'for', name) 20 print('占用字节: ', s.size) 21 print('打包结果: ', binascii.hexlify(packed_data)) 22 print('解包结果: ', s.unpack(packed_data))

1# output 2原始值 : (1, b'ab', 2.7) 3 4格式符 : b'@ I 2s f' for native, native 5占用字节: 12 6打包结果: b'0100000061620000cdcc2c40' 7解包结果: (1, b'ab', 2.700000047683716) 8 9格式符 : b'= I 2s f' for native, standard 10占用字节: 10 11打包结果: b'010000006162cdcc2c40' 12解包结果: (1, b'ab', 2.700000047683716) 13 14格式符 : b'< I 2s f' for little-endian 15占用字节: 10 16打包结果: b'010000006162cdcc2c40' 17解包结果: (1, b'ab', 2.700000047683716) 18 19格式符 : b'> I 2s f' for big-endian 20占用字节: 10 21打包结果: b'000000016162402ccccd' 22解包结果: (1, b'ab', 2.700000047683716) 23 24格式符 : b'! I 2s f' for network 25占用字节: 10 26打包结果: b'000000016162402ccccd' 27解包结果: (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()方法支持直接写入预先分配的缓冲区。

1import array 2import binascii 3import ctypes 4import struct 5 6s = struct.Struct('I 2s f') 7values = (1, 'ab'.encode('utf-8'), 2.7) 8print('原始值:', values) 9 10print() 11print('使用ctypes模块string buffer') 12 13b = ctypes.create_string_buffer(s.size) 14print('原始buffer :', binascii.hexlify(b.raw)) 15s.pack_into(b, 0, *values) 16print('打包结果写入 :', binascii.hexlify(b.raw)) 17print('解包 :', s.unpack_from(b, 0)) 18 19print() 20print('使用array模块') 21 22a = array.array('b', b'\0' * s.size) 23print('原始值 :', binascii.hexlify(a)) 24s.pack_into(a, 0, *values) 25print('打包写入 :', binascii.hexlify(a)) 26print('解包 :', s.unpack_from(a, 0))

1# output 2原始值: (1, b'ab', 2.7) 3 4使用ctypes模块string buffer 5原始buffer : b'000000000000000000000000' 6打包结果写入 : b'0100000061620000cdcc2c40' 7解包 : (1, b'ab', 2.700000047683716) 8 9使用array模块 10原始值 : b'000000000000000000000000' 11打包写入 : b'0100000061620000cdcc2c40' 12解包 : (1, b'ab', 2.700000047683716)

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

点赞
收藏

评论区

加载中...

相关推荐

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Python基础4——模块与包

12模块与包模块通俗地理解为.py文件,里面定义了变量、函数和类。需要的时候就可以导入这些模块。执行步骤1.在python模块加载路径中查找相应的模块文件2.将模块文件编译成中间代码3.执行模块文件中的代码12.1模块分类1.内置模块,也叫标准库,比如说random,time,大概有200多个2.第三方模块,也称为第三方库,使用pipins

java将前端的json数组字符串转换为列表

记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang

浅析Python模块的引入和调用

大家好,我是IT共享者,人称皮皮。这篇文章我们来浅析Python模块的引入和调用。一、前言Python中的模块,有过C语言编程经验的朋友都知道在C语言中如果要引用sqrt函数,必须用语句include引入math.h这个头文件,否则是无法正常进行调用的。那么在Python中,如果要引用一些其他的函数,该怎么处理呢?在Python中有一个概念叫做模块(mod

商业数据分析从入门到入职(8)Python模块、文件IO和面向对象

前言本文先介绍了Python中程序、模块和包的基本使用,并在此基础上介绍了Python标准库。然后详细介绍了Python中的文件IO操作,包括文本文件、二进制文件的读写和其他IO操作。最后介绍了面向对象,包括类的定义、继承的使用、鸭子类型和魔法方法。一、程序、模块和包1.自定义模块和包之前我们使用的.ipynb文件都不是纯Python文件,