Python规范库笔记

缓冲区

将数据打包成二进制平时是用在对品质必要非常高的光景。
在这里类场景中能够通过制止为种种打包结构分配新缓冲区的支出来优化。
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'' * 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)

博客原来的小说:

模块函数和Struct类

它除了提供叁个Struct类之外,还应该有很多模块级的函数用于拍卖结构化的值。这里有个格式符(Format
specifiers)的概念,是指从字符串格式转变为已编写翻译的象征情势,相仿刘恒则表明式的管理模式。日常实例化Struct类,调用类方法来形成改造,比一直调用模块函数有效的多。上边包车型地铁事例都以行使Struct类。

用途: 在Python基本数据类型和二进制数据里面开展转变

struct模块提供了用来在字节字符串和Python原生数据类型之间转移函数,举例数字和字符串。

格式符

格式符对照表如下:

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)

字节顺序/大小/对齐

暗中认可景况下,pack是应用本地C库的字节顺序来编码的。格式化字符串的首先个字符可以用来表示填充数据的字节顺序、大小和对齐格局,如下表所描述的:

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

假如格式符中未有设置那一个,那么暗中同意将应用 @

本地字节顺序是指字节顺序是由前段时间主机系统调整。比方:Intelx86和英特尔64(x86-64)使用小字节序; HTC 68000和 PowerPC
G5应用大字节序。ARM和AMD安腾扶持切换字节序。能够使用sys.byteorder查阅当前系统的字节顺序。

本土大小(Size)和对齐(阿里gnment)是由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)

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(),基本上再次回到相符的值(浮点数会有反差)。

该模块功效是完结Python数值和C语言结构体的Python字符串情势间的更动。那足以用来拍卖存款和储蓄在文书中或从网络连接中存款和储蓄的二进制数据,以致其它数据源。

发表评论

电子邮件地址不会被公开。 必填项已用*标注