Hello, everyone ~ I am a little bear cat duck
struct The module provides a string of bytes and Python Conversion functions between native data types , Such as numbers and strings .
The function of this module is to complete Python Sum of values C Of language structure Python Conversion between string forms .
This can be used to process binary data stored in files or from network connections , And other data sources .
In addition to providing a Struct Outside class , There are also many module level functions for dealing with structured values . Here is a formatter (Format specifiers) The concept of , It refers to the conversion from string format to compiled representation , Similar to regular expression processing . Usually instantiate Struct class , Call class methods to complete the transformation , It is much more effective than calling module functions directly .
The following examples all use Struct class .
Struct Support the transfer of data packing( pack ) String , And can reverse from the string unpacking( decompression ) Data .
In this case , Format specifier (specifier) Need an integer or long integer , A two byte string, And a floating point number . Spaces in the formatter are used to separate indicators (indicators), It will be ignored when compiling the format .
import struct
import binascii
values = (1, 'ab'.encode('utf-8'), 2.7)
s = struct.Struct('I 2s f')
packed_data = s.pack(*values)
print(' Original value :', values)
print(' Format symbol :', s.format)
print(' Occupied bytes :', s.size)
print(' Packing results :', binascii.hexlify(packed_data))
# output
Original value : (1, b'ab', 2.7)
Format symbol : b'I 2s f'
Occupied bytes : 12
Packing results : b'0100000061620000cdcc2c40'
This example converts the packed value into a hexadecimal byte sequence , use binascii.hexlify() Method print out .
Use unpack() How to unpack .
import struct
import binascii
packed_data = binascii.unhexlify(b'0100000061620000cdcc2c40')
s = struct.Struct('I 2s f')
unpacked_data = s.unpack(packed_data)
print(' Unpacking results :', unpacked_data)
# output
Unpacking results : (1, b'ab', 2.700000047683716)
Pass the packed value to unpack(), Basically return the same value ( Floating point numbers will vary ).
By default ,pack It's using local C The byte order of the Library . The first character of the format string can be used to indicate the byte order of the fill data 、 Size and alignment , The following table describes :
If these are not set in the formatter , Then the default will be @.
Local byte order means that the byte order is determined by the current host system . such as :Intel x86 and AMD64(x86-64) Use small byte order ; Motorola 68000 and PowerPC G5 Use large byte order .ARM and Intel Itanium supports switching byte order . have access to sys.byteorder Check the byte order of the current system .
Local size (Size) And alignment (Alignment) By c Compiler sizeof The expression determines . It corresponds to the local byte order .
The standard size is determined by the formatter , Next, we will talk about the standard sizes of various formats .
Example :
'''
No one answers the problems encountered in learning ? Xiaobian created a Python Exchange of learning QQ Group :660193417###
Looking for small partners who share the same aspiration , Help each other , There are also good video tutorials and PDF e-book !
'''
import struct
import binascii
values = (1, 'ab'.encode('utf-8'), 2.7)
print(' Original value : ', 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(' Format symbol : ', s.format, 'for', name)
print(' Occupied bytes : ', s.size)
print(' Packing results : ', binascii.hexlify(packed_data))
print(' Unpacking results : ', s.unpack(packed_data))
# output
Original value : (1, b'ab', 2.7)
Format symbol : b'@ I 2s f' for native, native
Occupied bytes : 12
Packing results : b'0100000061620000cdcc2c40'
Unpacking results : (1, b'ab', 2.700000047683716)
Format symbol : b'= I 2s f' for native, standard
Occupied bytes : 10
Packing results : b'010000006162cdcc2c40'
Unpacking results : (1, b'ab', 2.700000047683716)
Format symbol : b'< I 2s f' for little-endian
Occupied bytes : 10
Packing results : b'010000006162cdcc2c40'
Unpacking results : (1, b'ab', 2.700000047683716)
Format symbol : b'> I 2s f' for big-endian
Occupied bytes : 10
Packing results : b'000000016162402ccccd'
Unpacking results : (1, b'ab', 2.700000047683716)
Format symbol : b'! I 2s f' for network
Occupied bytes : 10
Packing results : b'000000016162402ccccd'
Unpacking results : (1, b'ab', 2.700000047683716)
The comparison table of format characters is as follows :
Packaging data into binary is usually used in scenarios that require high performance .
In such scenarios, it can be optimized by avoiding the overhead of allocating new buffers for each packaging structure .
pack_into() and unpack_from() Method supports writing directly to the pre allocated buffer .
import array
import binascii
import ctypes
import struct
s = struct.Struct('I 2s f')
values = (1, 'ab'.encode('utf-8'), 2.7)
print(' Original value :', values)
print()
print(' Use ctypes modular string buffer')
b = ctypes.create_string_buffer(s.size)
print(' original buffer :', binascii.hexlify(b.raw))
s.pack_into(b, 0, *values)
print(' Packaging results are written :', binascii.hexlify(b.raw))
print(' Unpack :', s.unpack_from(b, 0))
print()
print(' Use array modular ')
a = array.array('b', b'\0' * s.size)
print(' Original value :', binascii.hexlify(a))
s.pack_into(a, 0, *values)
print(' Pack and write :', binascii.hexlify(a))
print(' Unpack :', s.unpack_from(a, 0))
# output
Original value : (1, b'ab', 2.7)
Use ctypes modular string buffer
original buffer : b'000000000000000000000000'
Packaging results are written : b'0100000061620000cdcc2c40'
Unpack : (1, b'ab', 2.700000047683716)
Use array modular
Original value : b'000000000000000000000000'
Pack and write : b'0100000061620000cdcc2c40'
Unpack : (1, b'ab', 2.700000047683716)