Il modulo Python struct è usato per fornire una semplice interfaccia pitonica per accedere e manipolare il datatype structure del C. Questo può essere uno strumento utile se avete bisogno di trattare con il codice C e non avete il tempo di scrivere strumenti in C, dato che è un linguaggio di basso livello.

Questo modulo può convertire valori Python in una struttura C e viceversa. La struttura C è usata come un oggetto bytes di Python, dato che non c’è niente chiamato oggetto in C; solo strutture dati di dimensioni byte.

Capiamo come possiamo usare questo modulo per avere un’interfaccia Python alle strutture C.

Metodi del modulo Python struct

In questo modulo, dato che ci occupiamo di strutture C, guardiamo alcune delle funzioni che questo modulo ci fornisce.

struct.pack()

Questo è usato per impacchettare elementi in una stringa di byte Python (oggetto byte). Poiché la modalità di memorizzazione è basata sui byte, i programmi basati su C possono usare l’output di pack(), da un programma Python.

Format: struct.pack(format, v1, v2, …)

v1v2, … sono i valori che saranno imballati nell’oggetto byte. Rappresentano i valori dei campi per la struttura C. Poiché una struttura C che ha campi n deve avere esattamente valori n, gli argomenti devono corrispondere esattamente ai valori richiesti dal formato.

Qui, format si riferisce al formato del pacchetto. Questo è necessario poiché abbiamo bisogno di specificare il datatype della stringa di byte, come viene usato con il codice C. La tabella sottostante elenca i valori più comuni per format. Abbiamo bisogno di un formato per ogni valore per specificare il suo tipo di dati.

Formato C Datatype tipo Python
c carattere una stringa di lunghezza 1
? _Bool bool
h breve integrale
l lungo integrale
i int integrale
f float float
d double float
s carattere stringa

Comprendiamo questo usando alcuni esempi.

Lo snippet seguente memorizza i 3 interi 1, 2 e 3 in un oggetto byte usando pack(). Poiché la dimensione di un intero è di 4 byte sulla mia macchina, si vedono 3 blocchi di 4 byte, che corrispondono a 3 interi in C.

import struct# We pack 3 integers, so 'iii' is requiredvariable = struct.pack('iii', 1, 2, 3)print(type(variable), variable)variable_2 = struct.pack('iic', 1, 2, b'A')print('\n', variable_2)

Output

<class 'bytes'> b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'b'\x01\x00\x00\x00\x02\x00\x00\x00A'

Se il tipo appropriato non viene passato, l’eccezione struct.error sarà sollevata dal modulo Python struct.

import struct# Error!! Incorrect datatype assignmentvariable = struct.pack('ccc', 1, 2, 3)print(type(variable), variable)

Output

struct.error: char format requires a bytes object of length 1

struct.unpack()

Questa funzione del modulo struct di Python, scompatta il valore compresso nella sua rappresentazione originale secondo un formato appropriato. Restituisce una tupla di dimensione uguale al numero di valori passati da quando l’oggetto byte è spacchettato per dare gli elementi.

Formato: struct.unpack(format, string)

Questo scompatta il byte string secondo lo specificatore di formato format.

Questo è il contrario di struct.pack(). Prendiamo una delle vecchie stringhe di byte che abbiamo prodotto usando questo e proviamo a recuperare i valori python passati ad esso usando unpack().

import structbyte_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-stringtuple_vals = struct.unpack('iic', byte_str)print(tuple_vals)

Output

(1, 2, b'A')

Come potete vedere, infatti, possiamo impacchettare i nostri vecchi valori Python da questa tupla, a condizione di usare lo stesso specificatore di formato per entrambi pack() e unpack().

struct.calcsize()

Questa funzione restituisce la dimensione totale della rappresentazione String della struct usando un dato specificatore di formato, per recuperare i tipi di dati e calcolare la dimensione.

Formato: struct.calcsize(fmt)

import structprint('C Integer Size in Bytes:', struct.calcsize('i'))print('Size of 3 characters in Bytes:', struct.calcsize('ccc'))

Output

C Integer Size in Bytes: 4Size of 3 characters in Bytes: 3

struct.pack_into()

Questa funzione è usata per impacchettare valori in un buffer di stringhe Python, disponibile nel modulo ctypes.

Formato: struct.pack_into(fmt, buffer, offset, v1, v2, …)

Qui, fmt si riferisce allo specificatore del formato, come sempre. buffer è il buffer di stringhe che ora conterrà i valori confezionati, specificati. Potete anche specificare una offset posizione dall’indirizzo di base da cui avverrà l’impacchettamento.

Questo non restituisce alcun valore, e semplicemente memorizza i valori nella buffer stringa.

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 bufferbuff = 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 bufferprint(buff)

Output

<ctypes.c_char_Array_9 object at 0x7f4bccef1040>b'\x01\x00\x00\x00\x02\x00\x00\x00A'

Infine, otteniamo i nostri valori compressi nella stringa del buffer.

struct.unpack_from()

Simile a unpack(), esiste una controparte per scompattare i valori da una stringa buffer. Questo fa il contrario di struct.pack_into().

Formato: struct.unpack_from(fmt, buffer, offset)

Questo restituirà una tupla di valori, simile a 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 bufferbuff = 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))

Output

(1, 2, b'A')

Conclusione

In questo articolo, abbiamo imparato ad usare il modulo struct di Python per trattare con oggetti struttura di tipo C.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *