4.3 struct -- Interpreta le stringhe come dati binari impacchettati

Questo modulo effettua conversioni tra i valori Python e le strutture C rappresentate come stringhe Python. Utilizza delle stringhe di formattazione (spiegate di seguito) come descrizioni compatte del layout delle strutture C, e della conversione intesa da e verso i valori Python. Può venire impiegato per gestire dati binari memoprizzati su file o provienienti da una connessione di rete, come esempio di sorgenti di dati, fra i tanti possibili.

Il modulo definisce le sequenti eccezioni e funzioni:

exception error
Eccezione sollevata in varie occasioni; l'argomento è una stringa che descrive cosa non ha funzionato.

pack( fmt, v1, v2, ...)
Restituisce una stringa contenente i valori v1, v2, ... impacchettati in accordo con la formattazione data. Gli argomenti devono corrispondere esattamente ai valori richiesti dalla formattazione.

unpack( fmt, string)
Spacchetta la stringa (presumibilmente impacchettata da pack(fmt, ...)) in accordo col formato indicato. Il risultato è una tupla, anche se contiene esattamente un elemento. La stringa deve contenere esattamente la quantità di dati richiesta dalla stringa di formattazione. (len(string) deve essere uguale a calcsize(fmt)).

calcsize( fmt)
Restituisce la dimensione della struttura (e quindi della stringa) corrispondente al formato indicato.

I formatti dei caratteri hanno il seguente significato; la conversione tra C e i valori Python deve essere ovvia dati i loro tipi:

Formato  Tipo C  Python  Note 
x pad byte nessun valore  
c char stringa di lunghezza 1  
b signed char intero  
B unsigned char intero  
h short intero  
H unsigned short intero  
i int intero  
I unsigned int long  
l long intero  
L unsigned long long  
q long long long (1)
Q unsigned long long long (1)
f float float  
d double float  
s char[] stringa  
p char[] stringa  
P void * intero  

Note:

(1)
I codici di conversione "q" e "Q" sono disponibili in modo nativo solo se la piattaforma del compilatore C supporta il tipo C long long, o, su Windows, __int64. Sono sempre disponibili nei modi standard. Nuovo nella versione 2.2.

Un carattere di formattazione può essere preceduto da un intero indicante il conteggio delle ripetizioni. Per esempio, la stringa di formattazione '4h' è equivalente a 'hhhh'.

I caratteri di spaziatura tra i formati vengono ignorati; un contatore e il suo formato non devono venire separati da caratteri di spaziatura.

Per il carattere di formattazione "s", il contatore viene interpretato come la dimensione della stringa, non come un contatore delle ripetizioni come negli altri caratteri di formattazione; per esempio, '10s' indica una singola stringa di 10 byte, mentre '10c' indica 10 caratteri. Per l'impacchettamento, la stringa viene troncata o riempita con byte nulli, in numero tale da poterla adattare. Per lo spacchettamento, la stringa risultante ha sempre esattamente lo specificato numero di byte. Come caso speciale, '0s' indica una singola stringa vuota (mentre '0c' indica 0 caratteri).

Il carattere di formattazione "p" codifica una "stringa Pascal", cioè una breve stringa a lunghezza variabile memorizzata in un numero fisso di byte. Il contatore indica il numero totale di byte immagazzinati. Il primo byte immagazzinato indica la lunghezza della stringa, o 255, in caso sia inferiore. I byte della stringa vengono a seguire. Se la stringa passata a pack() è troppo lunga (maggiore del contatore meno 1), solo i count-1 byte iniziali della stringa vengono immagazzinati. Se la stringa è più corta di count-1, viene riempita di byte nulli così che vengano utilizzati esattamente count byte. Notate che per unpack(), il carattere di formattazione "p" consuma esattamente count byte, ma la stringa restituita non può contenere mai più di 255 caratteri.

Per i caratteri di formattazione "I", "L", "q" e "Q" il valore di ritorno è un intero long di Python.

Per il carattere di formattazione "P", il valore di ritorno è un intero semplice o long di Python, in funzione della dimensione necessaria per contenere un puntatore, una volta che sia stato convertito ad un valore intero. Un puntatore NULL verrà sempre restituito come il valore intero Python 0. Quando si impacchettano valori della dimensione di un puntatore, possono venire utilizzati interi semplici o long di Python. Per esempio, i processori Alpha e Merced usano puntatori a 64 bit, ovvero un intero long Python viene utilizzato per poter contenere il puntatore; le altre piattaforme utilizzano puntatori a 32 bit, e utilizzeranno un intero semplice Python.

In modo predefinito, i numeri C vengono rappresentati usando il formato e il byte order nativi, e correttamente allineati nell' utilizzo dei byte di riempimento se necessario (in accordo con le regole utilizzate dal compilatore C).

Alternativamente, il primo carattere della stringa di formattazione può venire utilizzato per indicare byte order, dimensione e allineamento dei dati impacchettati, in accordo con la tabella seguente:

Carattere  Byte order  Dimensione e allineamento 
@ nativo nativo
= nativo standard
< little-endian standard
> big-endian standard
! rete (= big-endian) standard

Se il primo carattere non è uno di questi, viene assunto "@".

Il byte order nativo può essere big-endian o little-endian, a seconda del sistema ospite. Per esempio, i processori Motorola e Sun sono big-endian; i processori Intel e DEC sono little-endian.

La dimensione e l'allineamento nativi vengono determinati utilizzando l'espressione sizeof del compilatore C. Questo viene sempre combinato con il byte order nativo.

La dimensione e l'allineamento standard sono come riportato di seguito: nessun allineamento viene richiesto per nessun tipo (perciò dovete utilizzare i byte di riempimento); short è di 2 byte; int e long sono di 4 byte; long long (__int64 su Windows) è di 8 byte; float e double sono numeri in virgola mobile in formato IEEE rispettivamente di 32 e 64 bit.

Notate la differenza tra "@" e "=": entrambi utilizzano il byte order nativo, ma la dimensione e l'allineamento dell'ultimo sono standarizzati.

La forma "!" è disponibile per quelle povere anime che si vantano di non ricordare se il byte order di rete è big-endian o little-endian.

Non c'è modo di indicare un byte order non nativo (forzare lo scambio dei byte); utilizzate la scelta appropriata di "<" o ">".

Il carattere di formattazione "P" è disponibile solo nel formato byte order nativo (selezionato come predefinito o con il carattere di byte order "@"). Il carattere di byte order "=" sceglie se usare l'ordinamento little-endian o big-endian in base al sistema ospite. Il modulo struct non interpreta questo come ordinamento nativo, perciò il formato "P" non è disponibile.

Esempi (usando sempre byte order, dimensione e allineamento nativi, su una macchina big-endian):

>>> from struct import *
>>> pack('hhl', 1, 2, 3)
'\x00\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('hhl', '\x00\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
>>> calcsize('hhl')
8

Suggerimento: per allineare la fine di una struttura ad un richiesto allineamento di tipo particolare, terminate il formato con il codice per quel tipo, con un contatore di ripetizioni di zero. Per esempio, il formato 'llh0l' specifica due byte di riempimento alla fine, assumendo che i long vengano allineati a 4 byte. Questo funziona solo quando si utilizzano dimensione ed allineamento nativi; dimensione e allineamento standard non fanno rispettare nessun allineamento.

Vedete anche:

Modulo array:
Immagazzinamento di dati binari omogenei.
Modulo xdrlib:
Impacchettamento e spacchettamento di dati XDR.
Vedete Circa questo documento... per informazioni su modifiche e suggerimenti.