modul struct v Pythonu
The modul struct v Krajta umožňuje pracovat s binárními daty tím, že poskytuje funkce pro převod mezi hodnotami Pythonu a binárními daty ve stylu C. To je užitečné zejména při práci s binárními formáty souborů nebo síťovými protokoly. Mezi jeho klíčové vlastnosti patří:
- Balení převést hodnoty Pythonu na binární data (bajty).
- Vybalování převést binární data zpět na hodnoty Pythonu.
- Formátovat řetězce definovat, jak jsou data sbalena/rozbalena pomocí formátových kódů (např. i pro celá čísla f pro plovoucí).
Metody v struct.pack()
1.Struct.pack(): Převádí hodnoty Pythonu do sbaleného binárního formátu. Formátovací řetězec (fmt) specifikuje rozložení komprimovaných dat a následné hodnoty (v1 v2 ...) jsou zabaleny podle tohoto formátu. Syntax:
struct.pack(fmt v1 v2 ...)
- fmt : Formátovací řetězec, který určuje, jak budou data zabalena.
- v1 v2 ...: Hodnoty, které budou zabaleny podle zadaného formátu.
import struct # pack values into binary var = struct . pack ( 'hhl' 1 2 3 ) print ( var ) var = struct . pack ( 'iii' 1 2 3 ) print ( var )
Výstup
b'x01x00x02x00x00x00x00x00x03x00x00x00x00x00x00x00' b'x01x00x00x00x02x00x00x00x03x00x00x00'
Vysvětlení: 'hhl' znamená dvě krátká celá čísla (h 2 bajty každé) následovaná dlouhým (l obvykle 4 nebo 8 bajtů v závislosti na platformě). 'iii' sbalí tři 4bajtová celá čísla. Výstup je v bajtech (b'') představujících binární kódování hodnot.
2.struct.unpack(): Převádí zabalená binární data zpět na hodnoty Pythonu. Vezme formátovací řetězec (fmt) a sbalený binární řetězec a vrátí n-tici rozbalených hodnot. Syntax:
struct.unpack(fmt řetězec)
- fmt: Formátovací řetězec, který určuje, jak mají být data rozbalena.
- řetězec: Zabalená binární data, která je třeba rozbalit.
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 )
Výstup
b'x01x00x02x00x05x00x00x00xbdx01x00x00x00x00x00x00' (True 2 5 445) b'x05x00x00x00x00x00x00x0033x13@' (5 2.299999952316284)
Vysvětlení: Tento příklad nejprve zabalí boolean (?), krátký (h), celé číslo (i) a dlouhý (l) do bajtů. Poté se použije struct.unpack() k převedení zpět na hodnoty Pythonu. Druhá část sbalí dlouhé dlouhé celé číslo (q) a float (f) a poté je rozbalí zpět. Všimněte si, jak se z 2.3 stane 2,299999952... kvůli přesnosti plovoucí.
3. struct.calcsize(): Vrací velikost (v bajtech) struktury odpovídající formátovacímu řetězci. Je to užitečné pro určení, kolik místa je potřeba k uložení zabalených dat. Syntax:
struct.calcsize(fmt)
- fmt: Formátovací řetězec, který určuje rozložení dat.
import struct print ( struct . calcsize ( '?hil' )) print ( struct . calcsize ( 'qf' ))
Výstup
16 12
Vysvětlení: '?hil' vyžaduje 16 bajtů a 'qf' potřebuje 12 bajtů v závislosti na zarovnání a platformě.
4. struct.pack_into() a struct.unpack_from(): Tyto metody umožňují přímo sbalit a rozbalit data do/z vyrovnávací paměti počínaje daným offsetem. Ty jsou zvláště užitečné při práci s předem přidělenými vyrovnávací paměti nebo při práci s binárními daty uloženými v paměti.
Syntaxe pro struct.pack_into():
struct.pack_into(fmt buffer offset v1 v2 ...)
- fmt: Formátovací řetězec určující rozložení dat.
- buffer: zapisovatelný buffer (např. ctypes.create_string_buffer).
- offset: Počáteční pozice ve vyrovnávací paměti, kde začíná balení.
- v1 v2 ...: Hodnoty, které mají být zabaleny do vyrovnávací paměti.
Syntaxe pro struct.unpack_from():
struct.unpack_from(fmt offset buffer=0)
- fmt: Formátovací řetězec určující rozložení dat.
- vyrovnávací paměť: Vyrovnávací paměť obsahující zabalená data.
- offset: Výchozí pozice, odkud začíná vybalování (volitelné)
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 )
Výstup
(2 2 3)
Vysvětlení: Zde je vytvořen buffer pomocí ctypes. struct.pack_into() vloží hodnoty do této vyrovnávací paměti se zadaným posunem (v tomto případě 0). struct.unpack_from() poté načte data zpět z vyrovnávací paměti.
Účinek pořadí formátu
Pořadí formátových znaků může změnit zabalený výstup kvůli odsazení a zarovnání. To ovlivňuje jak obsah bajtů, tak velikost výsledku.
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' ))
Výstup
b'8x00x00x00x15x14x13x12' 8 b'x15x14x13x128' 5
Vysvětlení: 'bi' (byte int) může obsahovat výplň za byte, zatímco 'ib' (int byte) nepotřebuje to. Rozdíl velikosti (8 vs 5) ukazuje, jak zarovnání ovlivňuje rozložení paměti.
Manipulační chyby
Pokud je s struct.pack() použit nesprávný datový typ, objeví se struct.error. K bezpečnému zvládnutí takových případů použijte try-kromě.
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 } ' )
Výstup
Struct Error: required argument is not an integer
Vysvětlení: To ukazuje zpracování chyb při použití struct. 'h' očekává krátké celé číslo, ale je zadán řetězec ('neplatný') způsobující struct.error. Blok try-except zachytí chybu a vytiskne smysluplnou zprávu.
Odkaz https://docs.python.org/2/library/struct.html
Vytvořit kvíz