Curs Avansat de Dezvoltare Python
Capitolul
>
Nivel
Module de serializare
Modul Struct
Scop
Configurați defalcarea finală a datelor pentru noul teren agricol folosind modulul struct.
La capătul drumului se află o stație de service care administrează noul teren agricol deja construit și culturile deja plantate. Aici vom inspecta și procesa datele privind culturile deja plantate și producția estimată a terenului agricol. La fel ca la celelalte nivele din acest capitol, vom lucra cu serializarea și deserializarea datelor, introducând un ultim modul denumit modulul struct.
Modulul struct introduce o serie de funcții de serializare care împachetează datele în format binar; spre deosebire de celelalte module cu care am lucrat, totuși, aveți un control mai mare asupra modului în care putem structura datele atât atunci când sunt serializate, cât și când sunt ulterior deserializate, făcându-l mai versatil decât alte module. Folosiți import struct pentru a accesa următoarele funcții pe care le vom utiliza pentru a procesa datele:
struct.calcsize(): Determină câți octeți sunt ocupați de un anumit șir de format, primind un (1) argument care reprezintă formatul al cărui dimensiune în octeți doriți să o verificați. Formatele pe care le vom utiliza sunt:- integer: reprezentat ca
'i'este formatul pentru date reprezentate ca numere întregi - float: reprezentat ca
'f'este formatul pentru date reprezentate ca numere zecimale - double: reprezentat ca
'd'este formatul pentru date reprezentate ca numere zecimale complexe, unde formatul float este insuficient.
- integer: reprezentat ca
struct.pack(): Serializează datele în format binar, împachetându-le într-un format la alegere. Aceasta poate primi două (2) sau mai multe argumente, și anume: formatul pe care doriți să-l utilizați și valorile pe care doriți să le serializați. Formatele sunt cele menționate anterior și trebuie adăugate corespunzător numărului de argumente furnizate.struct.unpack(): Deserializarează datele binare împachetate, primind două (2) argumente: formatul în care ar trebui să se conformeze datele, după cum au fost serialize, și al doilea, datele serialize.struct.iter_unpack(): Deserializarează date binare împachetate, funcționând la fel castruct.unpack()dar iterând prin fiecare bloc de date individual, prin utilizarea unui ciclu.struct.pack_into(): O versiune avansată astruct.pack(), primind patru (4) argumente: formatul pe care doriți să-l utilizați, bufferul de date în care doriți să introduceți datele, poziția din buffer în care doriți ca datele să fie plasate, și, în final, datele pe care le împachetați.struct.unpack_from(): O versiune avansată astruct.unpack(), primind trei (3) argumente: formatul pe care doriți să-l utilizați, bufferul de date din care doriți să deşerializați și, în final, poziția din buffer de unde doriți să deşerializați. Acest lucru vă permite să deşerializați porțiuni specifice ale datelor.
Mergeți la semnul X luminos din stația de service și îndreptați-vă spre birou, creați trei (3) variabile numite: integer, float și double. Le vom folosi pentru a verifica dimensiunea în octeți a fiecărui format folosind funcția struct.calcsize(). Pentru variabila integer utilizați funcția cu argumentul 'i', pentru variabila float utilizați funcția cu argumentul 'f' și, în final, pentru variabila double utilizați funcția cu argumentul 'd'. De exemplu: integer = struct.calcsize('i'). Adăugați cele trei (3) variabile la funcția write() pre-scrisă.
Mergeți la semnul X auriu și utilizați funcția read() pentru a colecta date despre noul teren agricol, notați punctele de date și formatul pentru utilizări viitoare, și anume: Resources, Size și Estimate. După ce ați notat aceste date, mergeți la semnul X luminos deasupra covorului albastru și creați o variabilă numită blue_data.
Cu variabila blue_data stocați valoarea funcției struct.pack(), setând ca argumente formatul și valorile pe care le-ați notat anterior. Când scrieți formatul, trebuie să „împachetați” tipurile de format într-o unitate unică. De exemplu, formatul pentru integer este notat ca 'i' după cum a fost detaliat, iar dacă adăugați trei tipuri de date integer, le adăugați astfel: 'iii'. În același mod, dacă adăugați un integer, un float și un double, se va scrie 'ifd'. Când adăugați datele, le introduceți individual ca argumente. Iată un exemplu general:
data_1 = 8 # is an integer data_2 = 2.25 # is a float data_3 = 900.702938103 # is a double blue_data = struct.pack('ifd', data_1, data_2, data_3)
Funcția struct.pack() oferă multă flexibilitate, permițându-vă să stabiliți modul în care doriți să formatați datele și să serializați mai multe puncte de date simultan, după cum doriți. Adăugați datele citite anterior folosind exemplul de mai sus ca bază. Folosiți funcția display() cu blue_data ca argument pentru a vizualiza datele împachetate.
Mergeți la semnul X întunecat deasupra covorului albastru și îndreptați-vă spre terminal, creați o variabilă numită blue_unpack și stocați valoarea funcției struct.unpack(), adăugând ca argumente același format folosit pentru împachetarea datelor și variabila blue_data. Formatul se scrie în același mod ca la funcția struct.pack(), astfel încât să puteți deşerializa datele în același mod în care le-ați serializat inițial. Folosiți funcția write() cu blue_unpack ca argument pentru a verifica datele pe care le-ați împachetat anterior.
La aceeași locație vom folosi și funcția struct.iter_unpack(), aceasta acceptând aceleași argumente ca struct.unpack(), dar fiind formatată ca un ciclu for, ceea ce ne permite să iterăm prin date, în loc să le afișăm pe toate deodată. Funcția este codificată astfel:
for values in struct.iter_unpack(-insert value-, -insert value-): player.speak(values)
Vom folosi funcția speak() pentru a afișa valorile; pentru argumentele lipsă din funcția struct.iter_unpack() adăugați aceleași valori folosite anterior cu struct.unpack(), deoarece acestea sunt variații ale aceleiași funcții, din punct de vedere al utilizării.
Mergeți la semnul X auriu deasupra covorului roșu și îndreptați-vă spre birou, utilizați funcția read() pentru a revizui cantitățile culturilor. Notați toate cantitățile și formatul pentru fiecare recoltă. Mergeți la semnul X luminos deasupra covorului roșu și creați un obiect numit buffer, și alocați-i valoarea bytearray(16). Acesta este un grup de octeți pe care îi putem adresa înainte de a-l popula; pentru scopurile noastre, funcționează ca un depozit de date unde puteți stoca datele manual. Numărul 16 ca argument reprezintă lungimea, adică numărul de octeți pe care îi puteți stoca în obiectul buffer.
Utilizați funcția struct.pack_into() pentru a popula obiectul buffer creat. Nu este necesar să creați o variabilă pentru a stoca valoarea funcției, deoarece funcția în sine va introduce valorile direct în obiectul buffer. Vom folosi funcția pentru fiecare dintre valorile notate anterior și le vom popula argumentele corespunzător.
De exemplu, pentru prima valoare a recoltelor furnizate, vi se va specifica formatul acesteia, poziția în octeți și cantitatea. Adăugați formatul ca prim argument, locația în care doriți să serializați octeții – în acest caz, buffer. Pentru al treilea argument setați poziția în care doriți să adăugați valoarea în interiorul buffer-ului; formatul determină numărul de octeți utilizați, așa că fiți atenți să împachetați date care nu au fost ocupate anterior. În final, adăugați valoarea pe care doriți să o serializați și să o introduceți în obiectul buffer.
struct.pack_into('i', buffer, 0, 82)
Obiectul buffer are 16 octeți, așa cum s-a menționat anterior; în codul de mai sus, formatul integer ocupă 4 octeți și este inserat la poziția 0. Aceasta înseamnă că, după ce datele sunt introduse în buffer, rămân doar 12 octeți neocupați în interiorul buffer-ului, cu pozițiile 0-3 ocupate de valoarea furnizată, în acest caz 82. Procedați astfel pentru toate punctele de date ale culturilor notate anterior, în total trei (3). Folosiți funcția display() și adăugați buffer pentru a afișa datele serializate.
Mergeți la semnul X întunecat deasupra covorului roșu și îndreptați-vă spre terminal, unde vom deserializa datele pentru a verifica conținutul și a asigura o stocare corectă. Creați trei variabile numite: lettuce, carrots și melons; vom deşerializa datele fiecărui punct individual. Pentru fiecare variabilă, stocați valoarea funcției struct.unpack_from() și setați ca argumente aceleași date notate pentru împachetarea datelor. Pentru primul argument setați formatul, pentru al doilea adăugați obiectul buffer din care se va deşerializa și, în final, poziția din buffer de unde doriți să deşerializați. De exemplu:
lettuce = struct.unpack_from('i', buffer, 0)
Aceste date corespund exemplului anterior de împachetare care este deşerializat; procedați la fel și pentru celelalte două variabile și introduceți lettuce, carrots și melons în funcția write() pre-scrisă pentru a finaliza nivelul.