modulo struct in Python
IL modulo struttura In Pitone ti consente di lavorare con dati binari fornendo funzionalità per la conversione tra valori Python e dati binari in stile C. Ciò è particolarmente utile quando si ha a che fare con formati di file binari o protocolli di rete. Le sue caratteristiche principali includono:
- Imballaggio convertire i valori Python in dati binari (byte).
- Disimballaggio riconvertire i dati binari in valori Python.
- Stringhe di formato definire come i dati vengono compressi/decompressi utilizzando i codici di formato (ad esempio i per numeri interi f per numeri in virgola mobile).
Metodi in struct.pack()
1.Struct.pack(): Converte i valori Python in un formato binario compresso. La stringa di formato (fmt) specifica il layout dei dati compressi e i valori successivi (v1 v2 ...) vengono compressi secondo questo formato. Sintassi:
struct.pack(fmt v1 v2 ...)
- fmt : una stringa di formato che specifica come verranno compressi i dati.
- v1 v2 ...: I valori che verranno compressi in base al formato specificato.
import struct # pack values into binary var = struct . pack ( 'hhl' 1 2 3 ) print ( var ) var = struct . pack ( 'iii' 1 2 3 ) print ( var )
Produzione
b'x01x00x02x00x00x00x00x00x03x00x00x00x00x00x00x00' b'x01x00x00x00x02x00x00x00x03x00x00x00'
Spiegazione: 'hhl' significa due interi brevi (h 2 byte ciascuno) seguiti da un numero lungo (l solitamente 4 o 8 byte a seconda della piattaforma). 'iii' racchiude tre numeri interi da 4 byte. L'output è in byte (b'') che rappresenta la codifica binaria dei valori.
2.struct.unpack(): Converte i dati binari compressi in valori Python. Richiede una stringa di formato (fmt) e una stringa binaria compressa e restituisce una tupla di valori non compressi. Sintassi:
struct.unpack(stringa fmt)
- fmt: Una stringa di formato che specifica come decomprimere i dati.
- corda: I dati binari compressi che devono essere decompressi.
import struct var = struct . pack ( '?hil' True 2 5 445 ) print ( var ) tup = struct . unpack ( '?hil' var ) print ( tup ) var = struct . pack ( 'qf' 5 2.3 ) print ( var ) tup = struct . unpack ( 'qf' var ) print ( tup )
Produzione
b'x01x00x02x00x05x00x00x00xbdx01x00x00x00x00x00x00' (True 2 5 445) b'x05x00x00x00x00x00x00x0033x13@' (5 2.299999952316284)
Spiegazione: Questo esempio innanzitutto comprime in byte un valore booleano (?), un valore short (h), un numero intero (i) e un valore long (l). Quindi struct.unpack() viene utilizzato per riconvertirlo in valori Python. La seconda parte impacchetta un intero long long (q) e un float (f), quindi li scompatta nuovamente. Nota come 2.3 diventa 2.299999952... a causa della precisione del float.
3. struct.calcsize(): Restituisce la dimensione (in byte) di una struttura corrispondente alla stringa di formato. È utile per determinare quanto spazio è necessario per archiviare i dati compressi. Sintassi:
struct.calcsize(fmt)
- fmt: una stringa di formato che specifica il layout dei dati.
import struct print ( struct . calcsize ( '?hil' )) print ( struct . calcsize ( 'qf' ))
Produzione
16 12
Spiegazione: '?hil' richiede 16 byte e 'qf' necessita di 12 byte a seconda dell'allineamento e della piattaforma.
4. struct.pack_into() e struct.unpack_from(): Questi metodi consentono di comprimere e decomprimere direttamente i dati in/da un buffer a partire da un determinato offset. Questi sono particolarmente utili quando si ha a che fare con buffer di memoria preassegnati o quando si lavora con dati binari archiviati in memoria.
Sintassi per struct.pack_into():
struct.pack_into(fmt buffer offset v1 v2 ...)
- fmt: una stringa di formato che specifica il layout dei dati.
- buffer: un buffer scrivibile (ad esempio ctypes.create_string_buffer).
- offset: la posizione iniziale nel buffer in cui inizia l'impaccamento.
- v1 v2 ...: i valori da inserire nel buffer.
Sintassi per struct.unpack_from():
struct.unpack_from(fmt buffer offset=0)
- fmt: Una stringa di formato che specifica il layout dei dati.
- respingente: Il buffer contenente i dati compressi.
- offset: La posizione iniziale da cui inizia il disimballaggio (facoltativo)
import struct import ctypes # Allocate buffer size = struct . calcsize ( 'hhl' ) buff = ctypes . create_string_buffer ( size ) # Pack into buffer struct . pack_into ( 'hhl' buff 0 2 2 3 ) # Unpack from buffer res = struct . unpack_from ( 'hhl' buff 0 ) print ( res )
Produzione
(2 2 3)
Spiegazione: Qui viene creato un buffer utilizzando ctypes. struct.pack_into() inserisce i valori in questo buffer all'offset specificato (0 in questo caso). struct.unpack_from() quindi rilegge i dati dal buffer.
Effetto dell'ordine dei formati
L'ordine dei caratteri del formato può modificare l'output compresso a causa del riempimento e dell'allineamento. Ciò influisce sia sul contenuto in byte che sulla dimensione del risultato.
Python import struct var = struct . pack ( 'bi' 56 0x12131415 ) print ( var ) print ( struct . calcsize ( 'bi' )) var = struct . pack ( 'ib' 0x12131415 56 ) print ( var ) print ( struct . calcsize ( 'ib' ))
Produzione
b'8x00x00x00x15x14x13x12' 8 b'x15x14x13x128' 5
Spiegazione: 'bi' (byte int) potrebbe includere il riempimento dopo il byte mentre 'ib' (int byte) non ne ha bisogno. La differenza di dimensione (8 vs 5) mostra come l'allineamento influisce sul layout della memoria.
Gestione degli errori
Se viene utilizzato il tipo di dati errato con struct.pack() si verifica un struct.error. Utilizzare try-eccetto per gestire questi casi in modo sicuro.
Python import struct try : struct . pack ( 'h' 'invalid' ) # Wrong type 'invalid' is a string but 'h' expects an integer except struct . error as e : print ( f 'Struct Error: { e } ' )
Produzione
Struct Error: required argument is not an integer
Spiegazione: Questo mostra la gestione degli errori quando si utilizza struct. 'h' si aspetta un intero breve ma viene fornita una stringa ('invalid') che causa un struct.error. Il blocco try-eccetto cattura l'errore e stampa un messaggio significativo.
Riferimento https://docs.python.org/2/library/struct.html
Crea quiz