struct — Interpreta bytes como paquetes de datos binarios

Código fuente: Lib/struct.py


This module converts between Python values and C structs represented as Python bytes objects. Compact format strings describe the intended conversions to/from Python values. The module’s functions and objects can be used for two largely distinct applications, data exchange with external sources (files or network connections), or data transfer between the Python application and the C layer.

Nota

When no prefix character is given, native mode is the default. It packs or unpacks data based on the platform and compiler on which the Python interpreter was built. The result of packing a given C struct includes pad bytes which maintain proper alignment for the C types involved; similarly, alignment is taken into account when unpacking. In contrast, when communicating data between external sources, the programmer is responsible for defining byte ordering and padding between elements. See Orden de bytes, tamaño y alineación for details.

Varias funciones struct (y métodos de Struct) toman un argumento buffer. Esto hace referencia a los objetos que implementan Protocolo búfer y proporcionan un búfer de lectura o de lectura/escritura. Los tipos más comunes utilizados para ese propósito son bytes y bytearray, pero muchos otros tipos que se pueden ver como una lista de bytes implementan el protocolo de búfer, para que se puedan leer/rellenar sin necesidad de copiar a partir de un objeto bytes.

Funciones y excepciones

El módulo define la siguiente excepción y funciones:

exception struct.error

Excepción lanzada en varias ocasiones; el argumento es una string que describe lo que está mal.

struct.pack(format, v1, v2, ...)

Retorna un objeto bytes que contiene los valores v1, v2, … empaquetado de acuerdo con la cadena de formato format. Los argumentos deben coincidir exactamente con los valores requeridos por el formato.

struct.pack_into(format, buffer, offset, v1, v2, ...)

Empaqueta los valores v1, v2, … de acuerdo con la cadena de formato format y escribe los bytes empaquetados en el búfer de escritura buffer comenzando en la posición offset. Nota: offset es un argumento obligatorio.

struct.unpack(format, buffer)

Desempaqueta del búfer buffer (normalmente empaquetado por pack(format, ...)) según la cadena de formato format. El resultado es una tupla incluso si contiene un solo elemento. El tamaño del búfer en bytes debe coincidir con el tamaño requerido por el formato, como se refleja en calcsize().

struct.unpack_from(format, /, buffer, offset=0)

Desempaqueta del buffer comenzando en la posición offset, según la cadena de formato format. El resultado es una tupla incluso si contiene un solo elemento. El tamaño del búfer en bytes, comenzando en la posición offset, debe tener al menos el tamaño requerido por el formato, como se refleja en calcsize().

struct.iter_unpack(format, buffer)

Iteratively unpack from the buffer buffer according to the format string format. This function returns an iterator which will read equally sized chunks from the buffer until all its contents have been consumed. The buffer’s size in bytes must be a multiple of the size required by the format, as reflected by calcsize().

Cada iteración produce una tupla según lo especificado por la cadena de formato.

Nuevo en la versión 3.4.

struct.calcsize(format)

Retorna el tamaño de la estructura (y, por lo tanto, del objeto bytes generado por pack(format, ...)) correspondiente a la cadena de formato format.

Cadenas de formato

Format strings describe the data layout when packing and unpacking data. They are built up from format characters, which specify the type of data being packed/unpacked. In addition, special characters control the byte order, size and alignment. Each format string consists of an optional prefix character which describes the overall properties of the data and one or more format characters which describe the actual data values and padding.

Orden de bytes, tamaño y alineación

By default, C types are represented in the machine’s native format and byte order, and properly aligned by skipping pad bytes if necessary (according to the rules used by the C compiler). This behavior is chosen so that the bytes of a packed struct correspond exactly to the memory layout of the corresponding C struct. Whether to use native byte ordering and padding or standard formats depends on the application.

Como alternativa, el primer carácter de la cadena de formato se puede utilizar para indicar el orden de bytes, el tamaño y la alineación de los datos empaquetados, según la tabla siguiente:

Carácter

Orden de bytes

Tamaño

Alineamiento

@

nativo

nativo

nativo

=

nativo

standard

none

<

little-endian

standard

none

>

big-endian

standard

none

!

red (= big-endian)

standard

none

Si el primer carácter no es uno de estos, se asume '@'.

Nota

The number 1023 (0x3ff in hexadecimal) has the following byte representations:

  • 03 ff in big-endian (>)

  • ff 03 in little-endian (<)

Python example:

>>> import struct
>>> struct.pack('>h', 1023)
b'\x03\xff'
>>> struct.pack('<h', 1023)
b'\xff\x03'

Native byte order is big-endian or little-endian, depending on the host system. For example, Intel x86, AMD64 (x86-64), and Apple M1 are little-endian; IBM z and many legacy architectures are big-endian. Use sys.byteorder to check the endianness of your system.

El tamaño y la alineación nativos se determinan mediante la expresión sizeof del compilador de C. Esto siempre se combina con el orden de bytes nativo.

El tamaño estándar depende únicamente del carácter de formato; ver la tabla en la sección Caracteres de formato.

Nótese la diferencia entre '@' y '=' : ambos utilizan el orden de bytes nativo, pero el tamaño y la alineación de este último está estandarizado.

La forma '!' representa el orden de bytes en la red, el cuál siempre es big-endian tal como se define en IETF RFC 1700.

No hay manera de indicar el orden de bytes no nativo (forzar el intercambio de bytes); utiliza la elección adecuada de '<' o '>'.

Notas:

  1. El relleno solo se agrega automáticamente entre los miembros sucesivos de la estructura. No se agrega ningún relleno al principio o al final de la estructura codificada.

  2. No se añade ningún relleno cuando se utiliza el tamaño y la alineación no nativos, por ejemplo, con “<”, “>”, “=” y “!”.

  3. Para alinear el final de una estructura con el requisito de alineación de un tipo determinado, termina el formato con el código de ese tipo con un conteo repetido de ceros. Véase Ejemplos.

Caracteres de formato

Los caracteres de formato tienen el siguiente significado; la conversión entre los valores de C y Python debe ser obvia dados sus tipos. La columna “Tamaño estándar” hace referencia al tamaño del valor empaquetado en bytes cuando se utiliza el tamaño estándar; es decir, cuando la cadena de formato comienza con uno de '<', '>', '!' o '='. Cuando se utiliza el tamaño nativo, el tamaño del valor empaquetado depende de la plataforma.

Formato

Tipo C

Tipo Python

Tamaño estándar

Notas

x

byte de relleno

sin valor

(7)

c

char

bytes de longitud 1

1

b

signed char

integer

1

(1), (2)

B

unsigned char

integer

1

(2)

(2)

_Bool

bool

1

(1)

h

short

integer

2

(2)

H

unsigned short

integer

2

(2)

i

int

integer

4

(2)

I

unsigned int

integer

4

(2)

l

long

integer

4

(2)

L

unsigned long

integer

4

(2)

q

long long

integer

8

(2)

Q

unsigned long long

integer

8

(2)

n

ssize_t

integer

(3)

N

size_t

integer

(3)

e

(6)

float

2

(4)

f

float

float

4

(4)

d

double

float

8

(4)

s

char[]

bytes

(9)

p

char[]

bytes

(8)

P

void*

integer

(5)

Distinto en la versión 3.3: Soporte añadido para los formatos 'n' y 'N'.

Distinto en la versión 3.6: Soporte añadido para el formato 'e'.

Notas:

  1. The '?' conversion code corresponds to the _Bool type defined by C99. If this type is not available, it is simulated using a char. In standard mode, it is always represented by one byte.

  2. When attempting to pack a non-integer using any of the integer conversion codes, if the non-integer has a __index__() method then that method is called to convert the argument to an integer before packing.

    Distinto en la versión 3.2: Added use of the __index__() method for non-integers.

  3. Los códigos de conversión 'n' y 'N' solo están disponibles para el tamaño nativo (seleccionado como predeterminado o con el carácter de orden de bytes '@'). Para el tamaño estándar, puedes usar cualquiera de los otros formatos enteros que se ajusten a tu aplicación.

  4. Para los códigos de conversión 'f', 'd' y 'e', la representación empaquetada utiliza el formato IEEE 754 binary32, binary64 o binary16 (para 'f', 'd' o 'e' respectivamente), independientemente del formato de punto flotante utilizado por la plataforma.

  5. El carácter de formato 'P' solo está disponible para el orden nativo de bytes (seleccionado como predeterminado o con el carácter de orden de bytes '@'). El carácter de orden de bytes '=' elige utilizar el orden little- o big-endian basado en el sistema host. El módulo struct no interpreta esto como un orden nativo, por lo que el formato 'P' no está disponible.

  6. El tipo IEEE 754 binary16 «half precision» se introdujo en la revisión de 2008 del IEEE 754 estándar. Tiene un bit de signo, un exponente de 5 bits y una precisión de 11 bits (con 10 bits almacenados explícitamente) y puede representar números entre aproximadamente 6.1e-05 y 6.5e+04 con total precisión. Este tipo no es ampliamente compatible con los compiladores de C: en un equipo típico, un unsigned short se puede usar para el almacenamiento, pero no para las operaciones matemáticas. Consulte la página de Wikipedia en el formato de punto flotante de media precisión para obtener más información.

  7. When packing, 'x' inserts one NUL byte.

  8. El carácter de formato 'p' codifica una «cadena de Pascal», lo que significa una cadena de longitud variable corta almacenada en un número fijo de bytes, dado por el recuento. El primer byte almacenado es el valor mínimo entre la longitud de la cadena o 255. A continuación se encuentran los bytes de la cadena. Si la cadena pasada a pack() es demasiado larga (más larga que la cuenta menos 1), solo se almacenan los bytes iniciales count-1 de la cadena. Si la cadena es más corta que count-1, se rellena con bytes nulos para que se utilicen exactamente los bytes de recuento en total. Tenga en cuenta que para unpack(), el carácter de formato 'p' consume bytes count, pero que la cadena retornada nunca puede contener más de 255 bytes.

  9. For the 's' format character, the count is interpreted as the length of the bytes, not a repeat count like for the other format characters; for example, '10s' means a single 10-byte string mapping to or from a single Python byte string, while '10c' means 10 separate one byte character elements (e.g., cccccccccc) mapping to or from ten different Python byte objects. (See Ejemplos for a concrete demonstration of the difference.) If a count is not given, it defaults to 1. For packing, the string is truncated or padded with null bytes as appropriate to make it fit. For unpacking, the resulting bytes object always has exactly the specified number of bytes. As a special case, '0s' means a single, empty string (while '0c' means 0 characters).

Un carácter de formato puede ir precedido de un número de recuento que repite tantas veces el carácter. Por ejemplo, la cadena de formato '4h' significa exactamente lo mismo que 'hhhh' .

Se omiten los caracteres de espacio entre formatos; sin embargo, un recuento y su formato no deben contener espacios en blanco.

Al empaquetar un valor x utilizando uno de los formatos enteros ('b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q'), si x está fuera de un rango válido para ese formato, entonces se lanza la excepción struct.error.

Distinto en la versión 3.1: Anteriormente, algunos de los formatos enteros ajustaban los valores fuera de rango y lanzaban DeprecationWarning en vez de struct.error.

Para el carácter de formato '?', el valor retornado es True o False. Al empaquetar, se utiliza el valor verdadero del objeto del argumento. Se empaquetará 0 o 1 en la representación bool nativa o estándar, y cualquier valor distinto de cero será True al desempaquetar.

Ejemplos

Nota

Native byte order examples (designated by the '@' format prefix or lack of any prefix character) may not match what the reader’s machine produces as that depends on the platform and compiler.

Pack and unpack integers of three different sizes, using big endian ordering:

>>> from struct import *
>>> pack(">bhl", 1, 2, 3)
b'\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('>bhl', b'\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
>>> calcsize('>bhl')
7

Attempt to pack an integer which is too large for the defined field:

>>> pack(">h", 99999)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
struct.error: 'h' format requires -32768 <= number <= 32767

Demonstrate the difference between 's' and 'c' format characters:

>>> pack("@ccc", b'1', b'2', b'3')
b'123'
>>> pack("@3s", b'123')
b'123'

Los campos desempaquetados se pueden nombrar asignándolos a variables o ajustando el resultado en una tupla con nombre:

>>> record = b'raymond   \x32\x12\x08\x01\x08'
>>> name, serialnum, school, gradelevel = unpack('<10sHHb', record)

>>> from collections import namedtuple
>>> Student = namedtuple('Student', 'name serialnum school gradelevel')
>>> Student._make(unpack('<10sHHb', record))
Student(name=b'raymond   ', serialnum=4658, school=264, gradelevel=8)

The ordering of format characters may have an impact on size in native mode since padding is implicit. In standard mode, the user is responsible for inserting any desired padding. Note in the first pack call below that three NUL bytes were added after the packed '#' to align the following integer on a four-byte boundary. In this example, the output was produced on a little endian machine:

>>> pack('@ci', b'#', 0x12131415)
b'#\x00\x00\x00\x15\x14\x13\x12'
>>> pack('@ic', 0x12131415, b'#')
b'\x15\x14\x13\x12#'
>>> calcsize('@ci')
8
>>> calcsize('@ic')
5

The following format 'llh0l' results in two pad bytes being added at the end, assuming the platform’s longs are aligned on 4-byte boundaries:

>>> pack('@llh0l', 1, 2, 3)
b'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00'

Ver también

Módulo array

Almacenamiento binario empaquetado de datos homogéneos.

Module json

JSON encoder and decoder.

Module pickle

Python object serialization.

Applications

Two main applications for the struct module exist, data interchange between Python and C code within an application or another application compiled using the same compiler (native formats), and data interchange between applications using agreed upon data layout (standard formats). Generally speaking, the format strings constructed for these two domains are distinct.

Native Formats

When constructing format strings which mimic native layouts, the compiler and machine architecture determine byte ordering and padding. In such cases, the @ format character should be used to specify native byte ordering and data sizes. Internal pad bytes are normally inserted automatically. It is possible that a zero-repeat format code will be needed at the end of a format string to round up to the correct byte boundary for proper alignment of consective chunks of data.

Consider these two simple examples (on a 64-bit, little-endian machine):

>>> calcsize('@lhl')
24
>>> calcsize('@llh')
18

Data is not padded to an 8-byte boundary at the end of the second format string without the use of extra padding. A zero-repeat format code solves that problem:

>>> calcsize('@llh0l')
24

The 'x' format code can be used to specify the repeat, but for native formats it is better to use a zero-repeat format like '0l'.

By default, native byte ordering and alignment is used, but it is better to be explicit and use the '@' prefix character.

Standard Formats

When exchanging data beyond your process such as networking or storage, be precise. Specify the exact byte order, size, and alignment. Do not assume they match the native order of a particular machine. For example, network byte order is big-endian, while many popular CPUs are little-endian. By defining this explicitly, the user need not care about the specifics of the platform their code is running on. The first character should typically be < or > (or !). Padding is the responsibility of the programmer. The zero-repeat format character won’t work. Instead, the user must explicitly add 'x' pad bytes where needed. Revisiting the examples from the previous section, we have:

>>> calcsize('<qh6xq')
24
>>> pack('<qh6xq', 1, 2, 3) == pack('@lhl', 1, 2, 3)
True
>>> calcsize('@llh')
18
>>> pack('@llh', 1, 2, 3) == pack('<qqh', 1, 2, 3)
True
>>> calcsize('<qqh6x')
24
>>> calcsize('@llh0l')
24
>>> pack('@llh0l', 1, 2, 3) == pack('<qqh6x', 1, 2, 3)
True

The above results (executed on a 64-bit machine) aren’t guaranteed to match when executed on different machines. For example, the examples below were executed on a 32-bit machine:

>>> calcsize('<qqh6x')
24
>>> calcsize('@llh0l')
12
>>> pack('@llh0l', 1, 2, 3) == pack('<qqh6x', 1, 2, 3)
False

Clases

El módulo struct también define el siguiente tipo:

class struct.Struct(format)

Return a new Struct object which writes and reads binary data according to the format string format. Creating a Struct object once and calling its methods is more efficient than calling module-level functions with the same format since the format string is only compiled once.

Nota

Las versiones compiladas de las cadenas de formato más recientes pasadas a Struct y las funciones de nivel de módulo se almacenan en caché, por lo que los programas que utilizan solo unas pocas cadenas de formato no necesitan preocuparse por volver a usar una sola instancia Struct.

Los objetos Struct compilados admiten los siguientes métodos y atributos:

pack(v1, v2, ...)

Idéntico a la función pack(), utilizando el formato compilado. (len(result) será igual a size.)

pack_into(buffer, offset, v1, v2, ...)

Idéntico a la función pack_into(), utilizando el formato compilado.

unpack(buffer)

Idéntico a la función unpack(), utilizando el formato compilado. El tamaño del búfer en bytes debe ser igual a size.

unpack_from(buffer, offset=0)

Idéntico a la función unpack_from(), utilizando el formato compilado. El tamaño del búfer en bytes, comenzando en la posición offset, debe ser al menos size.

iter_unpack(buffer)

Idéntico a la función iter_unpack(), utilizando el formato compilado. El tamaño del búfer en bytes debe ser un múltiplo de size.

Nuevo en la versión 3.4.

format

Cadena de formato utilizada para construir este objeto Struct.

Distinto en la versión 3.7: El tipo de cadena de formato es ahora str en lugar de bytes.

size

El tamaño calculado de la estructura (y, por lo tanto, del objeto bytes generado por el método pack()) correspondiente a format.