moduł struct w Pythonie
The moduł struktury W Pyton umożliwia pracę z danymi binarnymi, zapewniając funkcjonalność konwersji pomiędzy wartościami Pythona i danymi binarnymi w stylu C. Jest to szczególnie przydatne w przypadku binarnych formatów plików lub protokołów sieciowych. Jego najważniejsze cechy obejmują:
- Uszczelka
- Rozpakowywanie konwertuj dane binarne z powrotem na wartości Pythona.
- Formatuj ciągi zdefiniuj sposób pakowania/rozpakowywania danych za pomocą kodów formatu (np. i dla liczb całkowitych f dla zmiennoprzecinkowych).
Metody w struct.pack()
1.Struct.pack(): Konwertuje wartości Pythona na spakowany format binarny. Ciąg formatujący (fmt) określa układ spakowanych danych, a kolejne wartości (v1 v2 ...) są pakowane zgodnie z tym formatem. Składnia:
struct.pack(fmt v1 v2 ...)
- fmt : Ciąg formatujący określający sposób pakowania danych.
- v1 v2...: Wartości, które zostaną spakowane zgodnie z określonym formatem.
import struct # pack values into binary var = struct . pack ( 'hhl' 1 2 3 ) print ( var ) var = struct . pack ( 'iii' 1 2 3 ) print ( var )
Wyjście
b'x01x00x02x00x00x00x00x00x03x00x00x00x00x00x00x00' b'x01x00x00x00x02x00x00x00x03x00x00x00'
Wyjaśnienie: „hhl” oznacza dwie krótkie liczby całkowite (h 2 bajty każda), po których następuje długa (l zwykle 4 lub 8 bajtów w zależności od platformy). „iii” pakuje trzy 4-bajtowe liczby całkowite. Dane wyjściowe są wyrażone w bajtach (b'') reprezentujących kodowanie binarne wartości.
2.struktura.rozpakuj(): Konwertuje spakowane dane binarne z powrotem na wartości Pythona. Pobiera ciąg formatujący (fmt) i spakowany ciąg binarny i zwraca krotkę rozpakowanych wartości. Składnia:
struct.unpack(ciąg fmt)
- fmt: Ciąg formatu określający sposób rozpakowywania danych.
- smyczkowy: Spakowane dane binarne, które należy rozpakować.
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 )
Wyjście
b'x01x00x02x00x05x00x00x00xbdx01x00x00x00x00x00x00' (True 2 5 445) b'x05x00x00x00x00x00x00x0033x13@' (5 2.299999952316284)
Wyjaśnienie: W tym przykładzie najpierw pakowana jest wartość logiczna (?), krótka (h), liczba całkowita (i) i długa (l) w bajty. Następnie używana jest funkcja struct.unpack() do konwersji go z powrotem na wartości Pythona. Druga część pakuje długą, długą liczbę całkowitą (q) i liczbę zmiennoprzecinkową (f), a następnie rozpakowuje je z powrotem. Zwróć uwagę, że 2,3 staje się 2,299999952... ze względu na precyzję zmiennoprzecinkową.
3. struktura.calcsize(): Zwraca rozmiar (w bajtach) struktury odpowiadającej ciągowi formatującemu. Jest to pomocne przy określaniu, ile miejsca jest wymagane do przechowywania spakowanych danych. Składnia:
struct.calcsize(fmt)
- fmt: Ciąg formatujący określający układ danych.
import struct print ( struct . calcsize ( '?hil' )) print ( struct . calcsize ( 'qf' ))
Wyjście
16 12
Wyjaśnienie: „?hil” wymaga 16 bajtów i „qf” potrzebuje 12 bajtów w zależności od wyrównania i platformy.
4. struct.pack_into() i struct.unpack_from(): Metody te umożliwiają bezpośrednie pakowanie i rozpakowywanie danych do/z bufora, zaczynając od danego przesunięcia. Są one szczególnie przydatne, gdy mamy do czynienia ze wstępnie przydzielonymi buforami pamięci lub podczas pracy z danymi binarnymi przechowywanymi w pamięci.
Składnia struct.pack_into():
struct.pack_into(przesunięcie bufora fmt v1 v2 ...)
- fmt: Ciąg formatujący określający układ danych.
- bufor: zapisywalny bufor (np. ctypes.create_string_buffer).
- offset: Pozycja początkowa w buforze, w której rozpoczyna się pakowanie.
- v1 v2 ...: Wartości, które mają zostać spakowane do bufora.
Składnia dla struct.unpack_from():
struct.unpack_from(przesunięcie bufora fmt=0)
- fmt: Ciąg formatujący określający układ danych.
- bufor: Bufor zawierający spakowane dane.
- zrównoważyć: Pozycja wyjściowa, od której rozpoczyna się rozpakowywanie (opcjonalnie)
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 )
Wyjście
(2 2 3)
Wyjaśnienie: Tutaj tworzony jest bufor za pomocą ctypes. struktura.pack_into() wstawia wartości do tego bufora z określonym przesunięciem (w tym przypadku 0). struktura.rozpakuj_z() następnie odczytuje dane z bufora.
Wpływ kolejności formatów
Kolejność znaków formatu może zmienić spakowane dane wyjściowe z powodu dopełnienia i wyrównania. Ma to wpływ zarówno na zawartość bajtów, jak i rozmiar wyniku.
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' ))
Wyjście
b'8x00x00x00x15x14x13x12' 8 b'x15x14x13x128' 5
Objaśnienie: „bi” (bajt int) może zawierać dopełnienie po bajcie, podczas gdy „ib” (int bajt) nie potrzebuje tego. Różnica wielkości (8 vs 5) pokazuje, jak wyrównanie wpływa na układ pamięci.
Obsługa błędów
Jeśli w struct.pack() zostanie użyty niewłaściwy typ danych, wystąpi błąd struct. Użyj try-except, aby bezpiecznie obsługiwać takie przypadki.
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 } ' )
Wyjście
Struct Error: required argument is not an integer
Wyjaśnienie: To pokazuje obsługę błędów podczas używania struktury. „h” oczekuje krótkiej liczby całkowitej, ale podano ciąg znaków („nieprawidłowy”), powodując błąd struktury. Blok try-except przechwytuje błąd i wyświetla znaczący komunikat.
Odniesienie https://docs.python.org/2/library/struct.html
Utwórz quiz