The strukturni modul u Piton omogućuje vam rad s binarnim podacima pružajući funkcionalnost za pretvorbu između Python vrijednosti i C-style binarnih podataka. Ovo je osobito korisno kada se radi o binarnim formatima datoteka ili mrežnim protokolima. Njegove ključne karakteristike uključuju:
- Pakiranje pretvoriti Python vrijednosti u binarne podatke (bajtove).
- Raspakiranje pretvoriti binarne podatke natrag u Python vrijednosti.
- Format nizova definirajte kako se podaci pakiraju/otpakiraju pomoću kodova formata (npr. i za cijele brojeve f za float).
Metode u struct.pack()
1.Struct.pack(): Pretvara Python vrijednosti u upakirani binarni format. Niz formata (fmt) specificira raspored pakiranih podataka i sljedeće vrijednosti (v1 v2 ...) pakirane su u skladu s ovim formatom. Sintaksa:
struct.pack(fmt v1 v2 ...)
- fmt : niz formata koji određuje kako će podaci biti pakirani.
- v1 v2 ...: Vrijednosti koje će biti pakirane prema navedenom formatu.
import struct # pack values into binary var = struct.pack('hhl' 1 2 3) print(var) var = struct.pack('iii' 1 2 3) print(var)
Izlaz
b'x01x00x02x00x00x00x00x00x03x00x00x00x00x00x00x00' b'x01x00x00x00x02x00x00x00x03x00x00x00'
Objašnjenje: 'hhl' znači dva kratka cijela broja (h 2 bajta svaki) iza kojih slijedi dugi (l obično 4 ili 8 bajta ovisno o platformi). 'iii' pakira tri cijela broja od 4 bajta. Izlaz je u bajtovima (b'') koji predstavljaju binarno kodiranje vrijednosti.
2.struct.unpack(): Pretvara upakirane binarne podatke natrag u Python vrijednosti. Uzima formatni niz (fmt) i pakirani binarni niz i vraća torku nepakiranih vrijednosti. Sintaksa:
struct.unpack(fmt niz)
- fmt: Niz formata koji određuje kako se podaci trebaju raspakirati.
- niz: Zapakirani binarni podaci koje je potrebno raspakirati.
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)
Izlaz
b'x01x00x02x00x05x00x00x00xbdx01x00x00x00x00x00x00' (True 2 5 445) b'x05x00x00x00x00x00x00x0033x13@' (5 2.299999952316284)
Obrazloženje: Ovaj primjer prvo pakira booleov (?) kratki (h), cijeli (i) i dugi (l) u bajtove. Zatim se struct.unpack() koristi za pretvaranje natrag u Python vrijednosti. Drugi dio pakira dugi dugi cijeli broj (q) i float (f), a zatim ih otpakira natrag. Primijetite kako 2,3 postaje 2,299999952... zbog preciznosti float-a.
3. struct.calcsize(): Vraća veličinu (u bajtovima) strukture koja odgovara nizu formata. Korisno je za određivanje koliko je prostora potrebno za pohranjivanje pakiranih podataka. Sintaksa:
struct.calcsize(fmt)
- fmt: niz formata koji specificira raspored podataka.
import struct print(struct.calcsize('?hil')) print(struct.calcsize('qf'))
Izlaz
16 12
Objašnjenje: '?hil' zahtijeva 16 bajtova i 'qf' treba 12 bajtova ovisno o poravnanju i platformi.
4. struct.pack_into() i struct.unpack_from(): Ove vam metode omogućuju izravno pakiranje i raspakiranje podataka u/iz međuspremnika počevši od zadanog pomaka. Oni su osobito korisni kada se radi s unaprijed dodijeljenim međuspremnicima ili kada se radi s binarnim podacima pohranjenim u memoriji.
Sintaksa za struct.pack_into():
struct.pack_into(fmt pomak međuspremnika v1 v2 ...)
- fmt: niz formata koji specificira raspored podataka.
- međuspremnik: međuspremnik za pisanje (npr. ctypes.create_string_buffer).
- pomak: početni položaj u međuspremniku gdje počinje pakiranje.
- v1 v2 ...: Vrijednosti koje treba upakirati u međuspremnik.
Sintaksa za struct.unpack_from():
struct.unpack_from(fmt pomak međuspremnika=0)
- fmt: Niz formata koji specificira raspored podataka.
- pufer: Međuspremnik koji sadrži zapakirane podatke.
- pomak: Početna pozicija odakle počinje raspakiranje (nije obavezno)
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)
Izlaz
(2 2 3)
Obrazloženje: Ovdje se međuspremnik stvara pomoću ctype-ova. struct.pack_into() umeće vrijednosti u ovaj međuspremnik na navedenom pomaku (0 u ovom slučaju). struct.unpack_from() zatim čita podatke natrag iz međuspremnika.
Učinak redoslijeda formata
Redoslijed znakova formata može promijeniti upakirani izlaz zbog ispune i poravnanja. To utječe i na sadržaj bajtova i na veličinu rezultata.
Pythonimport 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'))
Izlaz
b'8x00x00x00x15x14x13x12' 8 b'x15x14x13x128' 5
Objašnjenje: 'bi' (bajt int) može uključivati punjenje nakon bajta dok 'ib' (int bajt) ne treba. Razlika u veličini (8 prema 5) pokazuje kako poravnanje utječe na raspored memorije.
Pogreške u rukovanju
Ako se koristi pogrešan tip podataka sa struct.pack(), javlja se struct.error. Koristite try-except za sigurno rješavanje takvih slučajeva.
Pythonimport 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}')
Izlaz
Struct Error: required argument is not an integer
Obrazloženje: Ovo pokazuje rukovanje pogreškama kada se koristi struct. 'h' očekuje kratki cijeli broj, ali je dan niz ('nevažeći') koji uzrokuje struct.error. Blok try-except bilježi pogrešku i ispisuje smislenu poruku.
Referenca https://docs.python.org/2/library/struct.html
kako pretvoriti niz u cijeli broj u Javi