Cours avancé de développement Python
Chapitre
>
Niveau
Modules de sérialisation
Module de Structure
Objectif
Mettez en place la répartition finale des données pour la nouvelle exploitation agricole en utilisant le module struct.
Au bout de la route se trouve une station-service qui administre la nouvelle exploitation agricole déjà construite ainsi que les cultures déjà plantées. Ici, nous allons examiner et traiter les données des cultures plantées et les prévisions de rendement de l'exploitation. Comme dans les autres niveaux de ce chapitre, nous allons travailler avec la sérialisation et la désérialisation des données, en introduisant un dernier module appelé le module struct.
Le module struct introduit une série de fonctions de sérialisation qui emballent les données en format binaire. Contrairement aux autres modules que nous avons utilisés, vous avez un contrôle plus précis sur la manière dont les données sont structurées lors de leur sérialisation et de leur désérialisation, ce qui le rend plus polyvalent. Utilisez import struct afin d’accéder aux fonctions suivantes que nous utiliserons pour traiter les données :
struct.calcsize(): Détermine combien d’octets sont utilisés pour empaqueter une chaîne de format donnée. Elle prend un (1) argument, à savoir le format dont vous souhaitez vérifier la taille en octets. Les formats que nous utiliserons sont :- integer : représenté par
'i', c’est le format pour les données sous forme de nombres entiers - float : représenté par
'f', c’est le format pour les données sous forme de nombres décimaux - double : représenté par
'd', c’est le format pour les données sous forme de nombres décimaux plus complexes lorsque le format float est insuffisant.
- integer : représenté par
struct.pack(): Sérialise les données en binaire, emballées dans un format de votre choix. Elle peut prendre deux (2) arguments ou plus, le premier étant le format que vous souhaitez utiliser et les suivants étant les valeurs que vous souhaitez sérialiser. Les formats sont ceux décrits précédemment et vous devez les ajouter en fonction du nombre d’arguments.struct.unpack(): Désérialise les données binaires emballées. Elle prend deux (2) arguments : le format qui doit correspondre à celui utilisé lors de la sérialisation, et les données qui ont été sérialisées.struct.iter_unpack(): Désérialise les données binaires emballées. Elle fonctionne de la même manière questruct.unpack(), mais elle itère sur chaque bloc de données individuellement à l’aide d’une boucle.struct.pack_into(): Version avancée destruct.pack(), elle prend quatre (4) arguments : le format que vous souhaitez utiliser, le buffer dans lequel vous souhaitez insérer les données, la position dans le buffer où les données doivent être placées, et enfin les données à emballer.struct.unpack_from(): Version avancée destruct.unpack(), elle prend trois (3) arguments : le format à utiliser, le buffer de données à désérialiser, et enfin la position dans le buffer à partir de laquelle désérialiser. Cela vous permet de désérialiser des portions spécifiques des données.
Marchez jusqu’au signe X lumineux dans la station-service et faites face au comptoir, créez trois (3) variables nommées : integer, float et double. Nous les utiliserons pour vérifier la taille en octets de chaque format en utilisant la fonction struct.calcsize(). Pour la variable integer, utilisez la fonction avec 'i' comme argument, pour la variable float utilisez la fonction avec 'f' comme argument et enfin pour la variable double utilisez la fonction avec 'd' comme argument. Par exemple : integer = struct.calcsize('i'). Ajoutez les trois (3) variables dans la fonction write() pré-écrite.
Marchez jusqu’au signe X doré et utilisez la fonction read() afin de recueillir des données sur la nouvelle exploitation agricole. Prenez note des points de données et du format pour une utilisation future, à savoir : Resources, Size et Estimate. Une fois cela fait, marchez jusqu’au signe X lumineux sur le tapis bleu et créez une variable nommée blue_data.
Avec la variable blue_data, stockez la valeur de la fonction struct.pack(), en définissant comme arguments le format et les valeurs que vous avez notés précédemment. Lors de l’écriture du format, vous devez « empaqueter » les types de format en une seule unité. Par exemple, le format entier est désigné par 'i' comme détaillé précédemment ; si vous ajoutez trois données entières, vous les écrirez comme 'iii'. De la même manière, si vous ajoutez un entier, un float et un double, ce sera écrit 'ifd'. Lors de l’ajout des données, vous les placez individuellement en tant qu’arguments. Voici un exemple global :
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)
La fonction struct.pack() offre beaucoup de flexibilité, vous permettant de définir comment formater les données et de sérialiser plusieurs points de données à la fois, selon votre convenance. Ajoutez les données lues précédemment en vous basant sur l’exemple ci-dessus. Utilisez la fonction display() avec blue_data en argument pour afficher les données emballées.
Marchez jusqu’au signe X sombre sur le tapis bleu et faites face au terminal, créez une variable nommée blue_unpack et stockez-y la valeur de la fonction struct.unpack(), en ajoutant comme arguments le même format utilisé pour emballer les données et la variable blue_data. Le format est écrit de la même manière que dans la fonction struct.pack(), de sorte que vous puissiez désérialiser les données de la même manière que vous les avez sérialisées. Utilisez la fonction write() avec blue_unpack en argument pour vérifier les données que vous avez précédemment emballées.
Au même endroit, nous allons également utiliser la fonction struct.iter_unpack(). Elle prend exactement les mêmes arguments que struct.unpack(), mais cette fois-ci, elle est placée dans une boucle for, ce qui nous permet d’itérer sur les données plutôt que de les afficher toutes d’un coup. La fonction est codée comme suit :
for values in struct.iter_unpack(-insert value-, -insert value-): player.speak(values)
Nous utiliserons la fonction speak() pour afficher les valeurs. Pour les arguments manquants dans la fonction struct.iter_unpack(), ajoutez les mêmes que ceux utilisés précédemment avec struct.unpack(), car il s’agit de variantes de la même fonction en termes d’utilisation.
Marchez jusqu’au signe X doré sur le tapis rouge et faites face au comptoir. Utilisez la fonction read() pour consulter les quantités des cultures. Prenez note de toutes les quantités et du format pour chaque culture. Ensuite, marchez jusqu’au signe X lumineux sur le tapis rouge et créez un objet nommé buffer, en lui assignant la valeur de bytearray(16). Il s’agit d’une collection d’octets que nous pouvons adresser avant de la remplir, et pour nos besoins, cela fonctionne comme une banque de données où vous pouvez stocker des informations manuellement. Le nombre 16 en argument indique le nombre d’octets pouvant être stockés dans l’objet buffer.
Utilisez la fonction struct.pack_into() pour remplir l’objet buffer que vous avez créé. Il n’est pas nécessaire de créer une variable pour stocker la valeur renvoyée par la fonction, car celle-ci insère directement les valeurs dans l’objet buffer. Nous allons utiliser cette fonction pour chacune des valeurs de culture que vous avez notées.
Par exemple, pour la première valeur de culture fournie, vous recevrez son format, sa position en octets et sa quantité. Ajoutez le format en premier argument, la localisation où vous souhaitez sérialiser les octets (dans ce cas buffer), pour le troisième argument, spécifiez la position dans le buffer où vous souhaitez placer la valeur (le format détermine le nombre d’octets utilisés, soyez donc attentif à ne pas écraser des données déjà présentes). Enfin, ajoutez la valeur que vous souhaitez sérialiser et insérer dans l’objet buffer.
struct.pack_into('i', buffer, 0, 82)
L’objet buffer possède 16 octets comme indiqué précédemment. Dans l’exemple de code ci-dessus, le format entier occupe 4 octets et est inséré à la position 0. Cela signifie qu’une fois les données insérées dans le buffer, il ne reste que 12 octets non occupés, la position 0 à 3 étant occupée par la valeur fournie, ici 82. Faites cela pour tous les points de données des cultures notées précédemment, il y en a trois (3) au total. Utilisez la fonction display() et ajoutez buffer pour afficher les données sérialisées.
Marchez jusqu’au signe X sombre sur le tapis rouge et faites face au terminal. Ici, nous allons désérialiser les données pour vérifier leur contenu et s’assurer qu’elles ont été stockées correctement. Créez trois variables nommées : lettuce, carrots et melons. Nous allons désérialiser les données de chaque point individuellement. Pour chacune de ces variables, stockez la valeur renvoyée par struct.unpack_from() en lui passant, comme arguments, les mêmes données que vous avez utilisées pour emballer les données. Pour le premier argument, définissez le format, pour le deuxième, ajoutez l’objet buffer d’où désérialiser, et enfin, spécifiez la position dans le buffer à partir de laquelle désérialiser. Par exemple :
lettuce = struct.unpack_from('i', buffer, 0)
Ces données correspondent à l’exemple d’emballage précédent en cours de désérialisation. Faites de même pour les deux autres variables et insérez lettuce, carrots et melons dans la fonction write() pré-écrite afin de compléter le niveau.