Python struct模块用于提供一个简单的 Pythonic 接口来访问和操作 C 的结构数据类型。如果您需要处理 C 代码并且没有时间用 C 编写工具(因为它是一种低级语言),那么这可能是一个方便的工具。
该模块可以将 Python 值转换为 C 结构,反之亦然。C 结构被用作 Python字节对象,因为 C 中没有所谓的对象;仅字节大小的数据结构。
让我们了解如何使用此模块来获得 C 结构的 Python 接口。
Python 结构体模块方法
在本模块中,由于我们关注的是 C 结构,因此让我们看一下该模块为我们提供的一些函数。
struct.pack()
这用于将元素打包到 Python 字节字符串(字节对象)中。由于存储模式基于字节,因此基于 C 的程序可以使用pack()
Python 程序中 , 的输出。
格式:struct.pack(格式, v1, v2, …)
v1
, v2
, … 是将被打包到字节对象中的值。它们代表 C 结构的字段值。由于具有字段的 C 结构n
必须完全具有n
值,因此参数必须与格式所需的值完全匹配。
这里,format
指的是包装的格式。这是必需的,因为我们需要指定字节串的数据类型,因为它与 C 代码一起使用。下表列出了 的最常见值format
。我们需要每个值一种格式来指定它的数据类型。
格式 | C 数据类型 | Python类型 |
c |
字符 | 长度为 1 的字符串 |
? |
_布尔 | 布尔值 |
h |
短的 | 整数 |
l |
长的 | 整数 |
i |
整数 | 整数 |
f |
漂浮 | 漂浮 |
d |
双倍的 | 漂浮 |
s |
字符[] | 细绳 |
让我们用一些例子来理解这一点。
下面的代码片段使用 将 3 个整数 1、2 和 3 存储在一个字节对象中pack()
。由于在我的机器上整数的大小为 4 个字节,因此您会看到 3 个 4 字节的块,这对应于 C 中的 3 个整数。
import struct # We pack 3 integers, so 'iii' is required variable = struct.pack( 'iii' , 1 , 2 , 3 ) print ( type (variable), variable) variable_2 = struct.pack( 'iic' , 1 , 2 , b 'A' ) print ( '\n' , variable_2) |
输出
< class 'bytes' > b '\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00' b '\x01\x00\x00\x00\x02\x00\x00\x00A' |
struct.error
如果未传递适当的类型, Python struct 模块将引发异常。
import struct # Error!! Incorrect datatype assignment variable = struct.pack( 'ccc' , 1 , 2 , 3 ) print ( type (variable), variable) |
输出
struct.error: char format requires a bytes object of length 1 |
struct.unpack()
Python struct 模块的此函数根据适当的格式将打包值解包为其原始表示形式。这将返回一个元组,其大小等于自字节对象被解包以提供元素以来传递的值的数量。
格式:struct.unpack(格式, 字符串)
string
这根据格式说明符解包字节format
。
这是相反的struct.pack()
。让我们获取使用它生成的旧字节字符串之一,并尝试使用 取回传递给它的 python 值unpack()
。
import struct byte_str = b '\x01\x00\x00\x00\x02\x00\x00\x00A' # Using the same format specifier as before, since # we want to get Python values for the same byte-string tuple_vals = struct.unpack( 'iic' , byte_str) print (tuple_vals) |
输出
( 1 , 2 , b 'A' ) |
pack()
正如您所看到的,实际上,只要我们对和 都使用相同的格式说明符,我们就可以从这个元组中获取旧的 Python 值unpack()
。
struct.calcsize()
此函数使用给定的格式说明符返回结构的字符串表示形式的总大小,以检索数据的类型并计算大小。
格式:struct.calcsize(fmt)
import struct print ( 'C Integer Size in Bytes:' , struct.calcsize( 'i' )) print ( 'Size of 3 characters in Bytes:' , struct.calcsize( 'ccc' )) |
输出
C Integer Size in Bytes: 4 Size of 3 characters in Bytes: 3 |
struct.pack_into()
此函数用于将值打包到模块中可用的 Python 字符串缓冲区中ctypes
。
格式:struct.pack_into(fmt, buffer, offset, v1, v2, …)
与往常一样,这里fmt
指的是格式说明符。buffer
是字符串缓冲区,现在将包含指定的打包值。您还可以指定offset
从基地址开始打包的位置。
这不会返回任何值,只是将值存储到buffer
字符串中。
import struct import ctypes # We will create a string buffer having a size # equal to that of a struct with 'iic' values. buf_size = struct.calcsize( 'iic' ) # Create the string buffer buff = ctypes.create_string_buffer(buf_size) # struct.pack() returns the packed data struct.pack_into( 'iic' , buff, 0 , 1 , 2 , b 'A' ) print (buff) # Display the contents of the buffer print (buff[:]) |
输出
<ctypes.c_char_Array_9 object at 0x7f4bccef1040 > b '\x01\x00\x00\x00\x02\x00\x00\x00A' |
事实上,我们在缓冲区字符串中获取了打包值。
struct.unpack_from()
与 类似unpack()
,存在用于从缓冲区字符串中解包值的对应项。这与struct.pack_into()
.
格式:struct.unpack_from(fmt, buffer, offset)
这将返回一个值的元组,类似于struct.unpack()
.
import struct import ctypes # We will create a string buffer having a size # equal to that of a struct with 'iic' values. buf_size = struct.calcsize( 'iic' ) # Create the string buffer buff = ctypes.create_string_buffer(buf_size) # struct.pack() returns the packed data struct.pack_into( 'iic' , buff, 0 , 1 , 2 , b 'A' ) print (struct.unpack_from( 'iic' , buff, 0 )) |
输出
( 1 , 2 , b 'A' ) |
结论
在这篇文章中,我们学习了如何使用Python struct模块来处理C类型的结构对象。
参考
- JournalDev 关于 Python struct 模块的文章