struct
— Tolka byte som packad binärdata¶
Källkod: Lib/struct.py
Denna modul konverterar mellan Python-värden och C-strukturer representerade som Python bytes
-objekt. Kompakta formatsträngar beskriver de avsedda konverteringarna till/från Python-värden. Modulens funktioner och objekt kan användas för två vitt skilda tillämpningar, datautbyte med externa källor (filer eller nätverksanslutningar) eller dataöverföring mellan Python-applikationen och C-lagret.
Anteckning
När inget prefixtecken anges är native-läge standard. Det packar eller packar upp data baserat på den plattform och kompilator som Python-tolken byggdes på. Resultatet av att packa en given C-struktur inkluderar padbytes som upprätthåller korrekt inriktning för de involverade C-typerna; på samma sätt beaktas inriktningen vid uppackning. När data kommuniceras mellan externa källor är det däremot programmeraren som ansvarar för att definiera byteordning och utfyllnad mellan element. Se Byteordning, storlek och inriktning för mer information.
Flera struct
-funktioner (och metoder i Struct
) tar ett buffer-argument. Detta hänvisar till objekt som implementerar Buffertprotokoll och tillhandahåller antingen en läsbar eller en skrivbar buffert. De vanligaste typerna som används för detta ändamål är bytes
och bytearray
, men många andra typer som kan ses som en array av bytes implementerar buffertprotokollet, så att de kan läsas/fyllas utan ytterligare kopiering från ett bytes
-objekt.
Funktioner och undantag¶
Modulen definierar följande undantag och funktioner:
- exception struct.error¶
Undantag som tas upp vid olika tillfällen; argumentet är en sträng som beskriver vad som är fel.
- struct.pack(format, v1, v2, ...)¶
Returnerar ett bytesobjekt som innehåller värdena v1, v2, … packade enligt formatsträngen format. Argumenten måste exakt matcha de värden som krävs av formatet.
- struct.pack_into(format, buffer, offset, v1, v2, ...)¶
Packa värdena v1, v2, … enligt formatsträngen format och skriv de packade bytena till den skrivbara bufferten buffer med start vid position offset. Observera att offset är ett obligatoriskt argument.
- struct.unpack(format, buffer)¶
Packar upp från bufferten buffer (förmodligen packad med
pack(format, ...)
) enligt formatsträngen format. Resultatet är en tupel även om den innehåller exakt ett objekt. Buffertens storlek i bytes måste matcha den storlek som krävs av formatet, vilket återspeglas avcalcsize()
.
- struct.unpack_from(format, /, buffer, offset=0)¶
Packar upp från buffer med start vid position offset, enligt formatsträngen format. Resultatet är en tupel även om den innehåller exakt ett objekt. Buffertens storlek i byte, med start vid position offset, måste vara minst den storlek som krävs av formatet, vilket återspeglas av
calcsize()
.
- struct.iter_unpack(format, buffer)¶
Iterativ uppackning från bufferten buffer enligt formatsträngen format. Denna funktion returnerar en iterator som läser lika stora bitar från bufferten tills allt dess innehåll har förbrukats. Buffertens storlek i bytes måste vara en multipel av den storlek som krävs av formatet, vilket återspeglas av
calcsize()
.Varje iteration ger en tupel som specificeras av formatsträngen.
Tillagd i version 3.4.
- struct.calcsize(format)¶
Returnerar storleken på struct (och därmed bytesobjektet som produceras av
pack(format, ...)
) som motsvarar formatsträngen format.
Format Strängar¶
Formatsträngar beskriver datalayouten vid packning och uppackning av data. De är uppbyggda av formattecken, som anger vilken typ av data som ska packas/packas upp. Dessutom styr specialtecken byteordning, storlek och inriktning. Varje formatsträng består av ett valfritt prefixtecken som beskriver de övergripande egenskaperna hos data och ett eller flera formattecken som beskriver de faktiska datavärdena och utfyllnaden.
Byteordning, storlek och inriktning¶
Som standard representeras C-typer i maskinens ursprungliga format och byteordning, och justeras korrekt genom att hoppa över padbytes om det behövs (enligt de regler som används av C-kompilatorn). Detta beteende är valt så att bytena i en packad struktur exakt motsvarar minneslayouten för motsvarande C-struktur. Huruvida man ska använda inbyggd byteordning och padding eller standardformat beror på applikationen.
Alternativt kan det första tecknet i formatsträngen användas för att ange byteordning, storlek och justering av de paketerade data, enligt följande tabell:
Tecken |
Byte-ordning |
Storlek |
Justering |
---|---|---|---|
|
infödd |
infödd |
infödd |
|
infödd |
standard |
ingen |
|
liten-endian |
standard |
ingen |
|
stor-endian |
standard |
ingen |
|
nätverk (= big-endian) |
standard |
ingen |
Om det första tecknet inte är något av dessa, antas '@'
.
Anteckning
Siffran 1023 (0x3ff
i hexadecimal) har följande byte representationer:
03 ff
i big-endian (>
)ff 03
i little-endian (<
)
Python exempel:
>>> import struct
>>> struct.pack('>h', 1023)
b'\x03\xff'
>>> struct.pack('<h', 1023)
b'\xff\x03'
Den inbyggda byteordningen är big-endian eller little-endian, beroende på värdsystemet. Till exempel är Intel x86, AMD64 (x86-64) och Apple M1 little-endian, medan IBM z och många äldre arkitekturer är big-endian. Använd sys.byteorder
för att kontrollera om ditt system är endianskt.
Ursprunglig storlek och inriktning bestäms med hjälp av C-kompilatorns sizeof
-uttryck. Detta kombineras alltid med inbyggd byteordning.
Standardstorleken beror endast på formattecknet; se tabellen i avsnittet Format tecken.
Observera skillnaden mellan '@'
och '='
: båda använder inbyggd byteordning, men storleken och inriktningen för den senare är standardiserad.
Formen '!'
representerar nätverkets byteordning som alltid är big-endian enligt definitionen i IETF RFC 1700.
Det finns inget sätt att ange en icke inhemsk byteordning (tvinga fram bytebyte); använd det lämpliga valet av '<'
eller '>'
.
Anteckningar:
Padding läggs bara automatiskt till mellan på varandra följande strukturmedlemmar. Ingen utfyllnad läggs till i början eller slutet av den kodade strukturen.
Ingen utfyllnad läggs till när man använder icke-nativ storlek och justering, t.ex. med ”<”, ”>”, ”=” och ”!”.
För att anpassa slutet av en struktur till anpassningskravet för en viss typ, avsluta formatet med koden för den typen med ett upprepningsantal på noll. Se Exempel.
Format tecken¶
Formattecken har följande betydelse; konverteringen mellan C- och Python-värden bör vara uppenbar med tanke på deras typer. Kolumnen ”Standardstorlek” avser storleken på det packade värdet i byte vid användning av standardstorlek, det vill säga när formatsträngen börjar med något av '<'
, '>'
, '!'
eller '='
. Vid användning av native-storlek är storleken på det packade värdet plattformsberoende.
Format |
C Typ |
Python-typ |
Standardstorlek |
Anteckningar |
---|---|---|---|---|
|
pad byte |
inget värde |
(7) |
|
|
char |
byte med längd 1 |
1 |
|
|
signed char |
heltal |
1 |
(1), (2) |
|
unsigned char |
heltal |
1 |
(2) |
|
_Bool |
bool |
1 |
(1) |
|
short |
heltal |
2 |
(2) |
|
unsigned short |
heltal |
2 |
(2) |
|
int |
heltal |
4 |
(2) |
|
unsigned int |
heltal |
4 |
(2) |
|
long |
heltal |
4 |
(2) |
|
unsigned long |
heltal |
4 |
(2) |
|
long long |
heltal |
8 |
(2) |
|
unsigned long long |
heltal |
8 |
(2) |
|
|
heltal |
(3) |
|
|
|
heltal |
(3) |
|
|
(6) |
flyt |
2 |
(4) |
|
float |
flyt |
4 |
(4) |
|
double |
flyt |
8 |
(4) |
|
float complex |
komplex |
8 |
(10) |
|
double complex |
komplex |
16 |
(10) |
|
char[] |
byte |
(9) |
|
|
char[] |
byte |
(8) |
|
|
void* |
heltal |
(5) |
Ändrad i version 3.3: Lagt till stöd för formaten 'n
och 'N
.
Ändrad i version 3.6: Stöd för formatet 'e'
har lagts till.
Ändrad i version 3.14: Stöd för formaten 'F
och 'D
har lagts till.
Anteckningar:
Konverteringskoden
'?'
motsvarar typen _Bool som definieras av C-standarder sedan C99. I standardläge representeras den av en byte.När du försöker packa ett icke-integertal med någon av koderna för heltalskonvertering, om icke-integertalet har en
__index__()
-metod, anropas den metoden för att konvertera argumentet till ett heltal före packning.Ändrad i version 3.2: Lagt till användning av metoden
__index__()
för icke-integraler.Konverteringskoderna
'n'
och'N'
är endast tillgängliga för den ursprungliga storleken (vald som standard eller med byteordningstecknet'@'
). För standardstorleken kan du använda vilket som helst av de andra heltalsformaten som passar din applikation.För konverteringskoderna
'f'
,'d'
och'e'
använder den packade representationen IEEE 754-formatet binary32, binary64 eller binary16 (för'f'
,'d'
respektive'e'
), oavsett vilket flyttalsformat som används av plattformen.Formattecknet
'P'
är endast tillgängligt för den ursprungliga byteordningen (vald som standard eller med byteordningstecknet'@'
). Byteordningstecknet'='
väljer att använda little- eller big-endian-ordning baserat på värdsystemet. Struct-modulen tolkar inte detta som inbyggd ordning, så formatet'P'
är inte tillgängligt.Typen IEEE 754 binary16 ”half precision” introducerades i 2008 års revision av IEEE 754-standarden. Den har en teckenbit, en 5-bitars exponent och 11-bitars precision (med 10 bitar explicit lagrade) och kan representera tal mellan cirka
6,1e-05
och6,5e+04
med full precision. Denna typ stöds inte allmänt av C-kompilatorer: på en typisk maskin kan en osignerad kort användas för lagring, men inte för matematiska operationer. Se Wikipedia-sidan om half-precision floating-point format för mer information.Vid packning infogar
'x'
en NUL-byte.Formattecknet
'p'
kodar en ”Pascal-sträng”, dvs. en kort sträng med variabel längd som lagras i ett fixerat antal byte, som anges av count. Den första byten som lagras är strängens längd eller 255, beroende på vilket som är minst. Därefter följer strängens byte. Om strängen som skickas tillpack()
är för lång (längre än count minus 1), lagras endast de förstacount-1
bytena i strängen. Om strängen är kortare äncount-1
fylls den på med nollbytes så att exakt count-bytes används. Observera att förunpack()
förbrukar formattecknet'p'
count
bytes, men att strängen som returneras aldrig kan innehålla mer än 255 bytes.För formattecknet
's'
tolkas antalet som längden på bytena, inte som ett upprepningsantal som för de andra formattecknen; till exempel betyder'10s'
en enda 10-bytessträng som mappar till eller från en enda Python-bytesträng, medan'10c'
betyder 10 separata en-bytes teckenelement (t.ex.cccccccccccc
) som mappar till eller från tio olika Python-byteobjekt. (Se Exempel för en konkret demonstration av skillnaden.) Om ett antal inte anges är standardvärdet 1. Vid packning trunkeras strängen eller fylls på med nollbytes på lämpligt sätt för att den ska få plats. Vid uppackning har det resulterande bytes-objektet alltid exakt det angivna antalet bytes. Som ett specialfall betyder'0s'
en enda, tom sträng (medan'0c'
betyder 0 tecken).För formattecknen
'F
och'D
använder den packade representationen IEEE 754 binary32- och binary64-formatet för komponenter i det komplexa talet, oavsett vilket flyttalsformat som används av plattformen. Observera att komplexa typer (F
ochD
) är tillgängliga villkorslöst, trots att komplexa typer är en valfri funktion i C. Enligt specifikationen i C11-standarden representeras varje komplex typ av en C-array med två element som innehåller den reella respektive imaginära delen.
Ett formattecken kan föregås av ett helt upprepningsantal. Till exempel betyder formatsträngen '4h'
exakt samma sak som 'hhhh'
.
Whitespace-tecken mellan format ignoreras; ett count och dess format får dock inte innehålla whitespace.
När du packar ett värde x
med ett av heltalsformaten ('b'
, 'B'
, 'h'
, 'H'
, 'i'
, 'I'
, 'l'
, 'L'
, 'q'
, 'Q'
), om x
är utanför det giltiga intervallet för det formatet, kommer struct.error
att visas.
Ändrad i version 3.1: Tidigare har vissa av heltalsformaten paketerat värden utanför intervallet och gett upphov till DeprecationWarning
istället för struct.error
.
För formattecknet '?'
är returvärdet antingen True
eller False
. Vid packning används argumentobjektets sanningsvärde. Antingen 0 eller 1 i den ursprungliga eller standard bool-representationen kommer att packas, och alla värden som inte är noll kommer att vara True
vid uppackning.
Exempel¶
Anteckning
Exempel på inbyggd byteordning (som betecknas med formatprefixet '@'
eller avsaknad av prefixtecken) kanske inte stämmer överens med vad läsarens maskin producerar eftersom det beror på plattform och kompilator.
Packa och packa upp heltal av tre olika storlekar, med big endian-ordning:
>>> from struct import *
>>> pack(">bhl", 1, 2, 3)
b'\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('>bhl', b'\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
>>> calcsize('>bhl')
7
Försök att packa ett heltal som är för stort för det definierade fältet:
>>> pack(">h", 99999)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
struct.error: 'h' format requires -32768 <= number <= 32767
Demonstrera skillnaden mellan formattecknen 's'
och 'c'
:
>>> pack("@ccc", b'1', b'2', b'3')
b'123'
>>> pack("@3s", b'123')
b'123'
Ouppackade fält kan namnges genom att de tilldelas variabler eller genom att resultatet förpackas i en namngiven tupel:
>>> record = b'raymond \x32\x12\x08\x01\x08'
>>> name, serialnum, school, gradelevel = unpack('<10sHHb', record)
>>> from collections import namedtuple
>>> Student = namedtuple('Student', 'name serialnum school gradelevel')
>>> Student._make(unpack('<10sHHb', record))
Student(name=b'raymond ', serialnum=4658, school=264, gradelevel=8)
Ordningsföljden på formattecknen kan påverka storleken i native-läge eftersom utfyllnaden är implicit. I standardläge är användaren ansvarig för att infoga önskad utfyllnad. Notera i det första pack
-anropet nedan att tre NUL-bytes lades till efter den packade '#'
för att anpassa följande heltal till en gräns på fyra byte. I det här exemplet producerades utdata på en little endian-maskin:
>>> pack('@ci', b'#', 0x12131415)
b'#\x00\x00\x00\x15\x14\x13\x12'
>>> pack('@ic', 0x12131415, b'#')
b'\x15\x14\x13\x12#'
>>> calcsize('@ci')
8
>>> calcsize('@ic')
5
Följande format 'llh0l'
resulterar i att två padbytes läggs till i slutet, förutsatt att plattformens longs är inriktade på 4-bytegränser:
>>> pack('@llh0l', 1, 2, 3)
b'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00'
Ansökningar¶
Det finns två huvudsakliga användningsområden för modulen struct
, datautbyte mellan Python- och C-kod inom ett program eller ett annat program som kompilerats med samma kompilator (native formats), och datautbyte mellan program som använder en överenskommen datalayout (standard formats). Generellt sett är formatsträngarna som konstrueras för dessa två domäner olika.
Ursprungliga format¶
Vid konstruktion av formatsträngar som efterliknar inbyggda layouter bestämmer kompilatorn och maskinarkitekturen byteordning och utfyllnad. I sådana fall bör formattecknet @
användas för att ange byteordning och datastorlek. Interna padbytes infogas normalt automatiskt. Det är möjligt att en formatkod med noll upprepningar behövs i slutet av en formatsträng för att avrunda till rätt bytegräns för korrekt justering av på varandra följande datapaket.
Tänk på dessa två enkla exempel (på en 64-bitars, little-endian-maskin):
>>> calcsize('@lhl')
24
>>> calcsize('@llh')
18
Data fylls inte ut till en 8-bytesgräns i slutet av den andra formatsträngen utan att extra utfyllnad används. En formatkod med noll upprepningar löser det problemet:
>>> calcsize('@llh0l')
24
Formatkoden 'x'
kan användas för att ange upprepningen, men för inbyggda format är det bättre att använda ett format med noll upprepning som '0l'
.
Som standard används inbyggd byteordning och justering, men det är bättre att vara tydlig och använda prefixtecknet '@'
.
Standardformat¶
När du utbyter data utanför din process, t.ex. nätverk eller lagring, ska du vara exakt. Ange den exakta byteordningen, storleken och inriktningen. Anta inte att de matchar den ursprungliga ordningen för en viss maskin. Till exempel är byteordningen i nätverk big-endian, medan många populära processorer är little-endian. Genom att definiera detta explicit behöver användaren inte bry sig om detaljerna i den plattform som deras kod körs på. Det första tecknet bör normalt vara <
eller >
(eller !
). Utfyllnad är programmerarens ansvar. Formattecknet med noll upprepningar fungerar inte. Istället måste användaren uttryckligen lägga till 'x'
padbytes där det behövs. Om vi återgår till exemplen från föregående avsnitt har vi:
>>> calcsize('<qh6xq')
24
>>> pack('<qh6xq', 1, 2, 3) == pack('@lhl', 1, 2, 3)
True
>>> calcsize('@llh')
18
>>> pack('@llh', 1, 2, 3) == pack('<qqh', 1, 2, 3)
True
>>> calcsize('<qqh6x')
24
>>> calcsize('@llh0l')
24
>>> pack('@llh0l', 1, 2, 3) == pack('<qqh6x', 1, 2, 3)
True
Det är inte säkert att resultaten ovan (som kördes på en 64-bitars maskin) stämmer överens när de körs på andra maskiner. Exemplen nedan kördes till exempel på en 32-bitars maskin:
>>> calcsize('<qqh6x')
24
>>> calcsize('@llh0l')
12
>>> pack('@llh0l', 1, 2, 3) == pack('<qqh6x', 1, 2, 3)
False
Klasser¶
Modulen struct
definierar också följande typ:
- class struct.Struct(format)¶
Returnerar ett nytt Struct-objekt som skriver och läser binära data enligt formatsträngen format. Att skapa ett
Struct
-objekt en gång och anropa dess metoder är mer effektivt än att anropa funktioner på modulnivå med samma format eftersom formatsträngen bara kompileras en gång.Anteckning
De kompilerade versionerna av de senaste formatsträngarna som skickas till modulnivåfunktionerna cachas, så program som bara använder ett fåtal formatsträngar behöver inte oroa sig för att återanvända en enda
Struct
-instans.Kompilerade Struct-objekt har stöd för följande metoder och attribut:
- pack(v1, v2, ...)¶
Identisk med funktionen
pack()
, med det kompilerade formatet. (len(result)
kommer att motsvarasize
.)
- pack_into(buffer, offset, v1, v2, ...)¶
Identisk med funktionen
pack_into()
, med det kompilerade formatet.
- unpack(buffer)¶
Identisk med funktionen
unpack()
, men använder det kompilerade formatet. Buffertens storlek i bytes måste vara lika medsize
.
- unpack_from(buffer, offset=0)¶
Identisk med funktionen
unpack_from()
, men använder det kompilerade formatet. Buffertens storlek i byte, med start vid position offset, måste vara minstsize
.
- iter_unpack(buffer)¶
Identisk med funktionen
iter_unpack()
, men använder det kompilerade formatet. Buffertens storlek i bytes måste vara en multipel avsize
.Tillagd i version 3.4.
- format¶
Den formatsträng som användes för att konstruera detta Struct-objekt.
- size¶
Den beräknade storleken på struct (och därmed på bytesobjektet som produceras av metoden
pack()
) som motsvararformat
.
Ändrad i version 3.13: repr() för structs har ändrats. Det är det nu:
>>> Struct('i') Struct('i')