4.3 struct --- Interprête les chaines de caractères comme paquet de données binaires

Ce module effectue des conversions entre des valeurs Python et des structures C représentées par des chaines de caractères Python. Il utilise des chaines de caractères formatées (expliquations plus loin) comme description compacte du schéma des structures C et la conversion voulue de/vers les valeurs Python. Cela peut être utilisé pour traiter des données binaires stoquées dans des fichiers ou provenant de connexions réseau, entre autres sources.

Ce module définit l'exception et les fonctions suivantes :

error
Exception levée en diverses occasions; l'argument est une chaine de caractères décrivant ce qui est mauvais.

pack(fmt, v1, v2, ...)
Retourne une chaine de caractères contenant les valeurs v1, v2, ... groupées selon le format donné. Les arguments doivent correspondre exactement aux valeurs requises par le format.

unpack(fmt, string)
Dépaquete la chaine de caractères (présumée empaqueter par pack(fmt, ...)) selon le format donné. Le resultat est un tuple même s'il contient qu'un article. La chaine de caractères doit contenir exactement le volume de données requis par le format (i.e. len(string) doit valoir calcsize(fmt)).

calcsize(fmt)
Retourne la taille de la structure (et de là, de la chaine de caractères) correspondant au format donné.

Les caractères de format ont la signification suivante ; la conversion entre les valeurs C et Python doit évidemment donner leurs types:

Format C Type Python 
Notes
xpad bytepas de valeur 
c charchaine de caractères de longueur 1 
b signed charentier 
B unsigned charentier 
h shortentier 
H unsigned shortentier 
i intentier 
I unsigned intlong(1)
l longentier 
L unsigned longlong 
f floatflottant 
d doubleflottant 
s char[]chaine de caractères 
p char[]chaine de caractères 
P void *entier 

Notes:

(1)
Le code de conversion "I" convertira dans un entier long Python si l'entier C est de la même taille qu'un entier long en C, ce qui le cas sur la plupart des systèmes modernes. Si un entier C est plus petit qu'un long C, un entier Python sera créé à la place.

Un caractère de format peut être précédé par un compteur intégral répétitif ; par exemple la chaine de format '4h' signifie exactement la même chose que 'hhhh'.

Les espaces entre les formats sont ignorés ; un compteur et son format ne doit pas contenir d'espace cependant.

Pour le caractère de format "s", le compteur représente la taille de la chaine de caractère, et non un compteur de répétition comme pour les autres caractères de format ; e.g. '10s' signifie une simple chaine de 10 octets, tandis que '10c' signifie 10 caractères. Pour l'empaquetage, la chaine est tronquée ou comblée avec des octets nuls si nécessaire. Pour le dépaquage, la chaine de résultat a toujours exactement le nombre d'octets spécifié. Cas particulier, '0s' signifie une simple chaine vide (tandis que '0c' signifie 0 caractères).

Le caractère de format "p" peut être utilisé pour encoder une chaine de caractère Pascal. Le premier octet est la longueur de la chaine stockée, avec les octets de la chaine suivante. Si le compteur est donné, il représente le nombre total d'octets utilisé, en inluant l'octet de longueur. Si la chaine passée à pack() est trop longue, la représentation stockée est tronquée. Si la chaine est trop courte, elle est est comblée pour obtenir exactement le nombre d'octets du compteur.

Avec les caractères de format "I" et "L", la valeur retournée est un entier long Python.

Pour le caractère de format "P", la valeur retournée est un entier Python ou un entier long, en fonction de la taille necessaire pour stocker un pointeur transformé en type entier. Un pointeur NULL sera toujours retourné comme un entier 0 Python. Pour empaqueter des valeurs dépendantes de pointeurs, un entier Python ou un entier long peut être utilisé. Par exemple, les processeurs Alpha et Merced ayant des pointeurs de données 64-bit, un entier long Python sera utilisé pour stocker le pointeur ; les autres plateformes ayant des pointeurs 32-bit, un entier Python sera utilisé.

Par défaut, les nombres C sont représentés dans le format natif de la machine, en respectant l'ordre des octets et alignés proprement en omettant les octets de complément si nécessaire (en accord avec les règles utilisées par le compilateur C).

Ou bien le premier caractère de la chaine de format peut être utilisé pour indiquer l'ordre des octets, la taille et l'alignement des données empaquetées, en accord avec la table suivante :

Caractère Ordre des octets Taille et alignement 
@natifnatif
=natifstandard
<little-endianstandard
>big-endianstandard
!réseaux (= big-endian)standard

Si le premier caractère n'est aucun de ceux-ci, "@" est utilisé.

L'ordre natif des octets est big-endian ou little-endian, en fonction du système hôte (e.g. Motorola et Sun sont big-endian ; Intel et DEC sont little-endian).

La taille et l'alignement natif sont déterminés en utilisant l'expression sizeof du compilateur C. C'est toujours combiné avec l'ordre natif des octets.

La taille et l'alignement standard sont comme suit : aucun alignement n'est requis pour aucun type (alors vous devez utiliser des octets pour compléter) ; short est sur 2 octets ; int et long sont sur 4 octets. float et double sont des nombres flottants IEEE 32-bit et 64-bit, respectivement.

Noter la différence entre "@" et "=": Les deux utilisent l'ordre natif des octets, mais la taille et l'alignement du dernier est standardisé.

La forme "!" est disponible pour ces pauvres âmes qui clament qu'ils ne peuvent jamais se souvenir si l'ordre des octets sur le réseaux est big-endian ou little-endian.

Il n'y a pas de façon d'indiquer un ordre des octets non-natif (i.e. pour forcer l'échange des octets) ; Il faut utiliser le choix approprié "<" ou ">".

Le caractère de format "P" est seulement disponible l'ordre natif des octets ( par défaut ou avec le caractère d'ordre des octets "@" ). Le caractère d'ordre des octets "=" choisit d'utiliser l'ordre little- ou big-endian basé sur le système hôte. Le module struct n'interprête pas cet ordre natif, alors le format "P" n'est pas disponible.

Exemples (tous utilisent l'ordre natif des octets, taille et alignement, sur une machine big-endian) :

 >>> from struct import *
 >>> pack('hhl', 1, 2, 3)
 '\000\001\000\002\000\000\000\003'
 >>> unpack('hhl', '\000\001\000\002\000\000\000\003')
 (1, 2, 3)
 >>> calcsize('hhl')
 8

Truc : pour aligner la fin de la structure sur l'alignement requis d'un type particulier, terminer le format avec le code de ce type avec un zéro, e.g. le format 'llh0l' spécifie deux octets comblés à la fin, en considérant que les longs sont alignés sur des bornes de 4 octets. Cela ne marche que si la taille native et l'alignement sont effectifs ; la taille standard et l'alignement ne force aucun alignement.

Voir aussi:

Module array:
Stockage de données binaires homogènes.
Module xdrlib:
Empaqueter et dépaqueter des données XDR.