2010-04-10 5 views
15

Python dit que je besoin de 4 octets pour un code de format de « BH »:struct.error: Déballez nécessite un argument de chaîne de longueur 4

struct.error: unpack requires a string argument of length 4 

Voici le code, je suis en train en 3 octets que je penser est nécessaire: (!?)

major, minor = struct.unpack("BH", self.fp.read(3)) 

"B" unsigned char (1 octet) + "H" unsigned short (2 octets) = 3 octets

struct.calcsize ("BH") dit 4 octets.

EDIT: Le fichier est ~ 800 Mo et il est dans les premiers octets du fichier, donc je suis assez certain qu'il reste des données à lire.

Répondre

20

Le module struct imite les structures C. Il faut plus de cycles CPU pour qu'un processeur lise un mot de 16 bits sur une adresse impaire ou un mot de 32 bits sur une adresse non divisible par 4, donc les structures ajoutent des octets de pad pour que les membres de la structure tombent sur des limites naturelles. Considérons:

struct {     11 
    char a; 
    short b;  ------------ 
    char c;  axbbcxxxdddd 
    int d; 
}; 

Cette structure occupera 12 octets de mémoire (x étant des octets de pad).

Python fonctionne de façon similaire (voir la documentation struct):

>>> import struct 
>>> struct.pack('BHBL',1,2,3,4) 
'\x01\x00\x02\x00\x03\x00\x00\x00\x04\x00\x00\x00' 
>>> struct.calcsize('BHBL') 
12 

Compilateurs ont généralement un moyen d'éliminer le rembourrage. En Python, l'un des = <>! supprimera le remplissage:

>>> struct.calcsize('=BHBL') 
8 
>>> struct.pack('=BHBL',1,2,3,4) 
'\x01\x02\x00\x03\x04\x00\x00\x00' 

Méfiez-vous de laisser le rembourrage struct handle. En C, ces structures:

struct A {  struct B { 
    short a;   int a; 
    char b;   char b; 
};    }; 

sont typiquement 4 et 8 octets, respectivement. Le remplissage se produit à la fin de la structure dans le cas où les structures sont utilisées dans un tableau. Cela maintient les membres 'a' alignés sur les limites correctes pour les structures plus tard dans le tableau. Le module struct Python ne gonflez pas à la fin:

>>> struct.pack('LB',1,2) 
'\x01\x00\x00\x00\x02' 
>>> struct.pack('LBLB',1,2,3,4) 
'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04' 
+1

Ce que je me demande, c'est pourquoi Python n'a pas emballé les données dans un tel format en premier lieu. "01 01 00" il a empaqueté l'octet 0x01, court 0x01, mais essaye de le déballer comme "01 00 01 00". Quoi qu'il en soit, j'ai résolu mon problème, j'ajoute toujours '<' devant tous mes codes de format, pour les rendre peu endiablés. Merci pour l'explication. :) –

+0

avait un problème similaire, le '=' ni '@' n'a pas résolu ... en utilisant le code que j'ai fait sur mac sur windows – jokoon

+0

@ThomasO Pourquoi dites-vous qu'il emballe comme "01 01 00"? Je vois struct.pack ('BH', 1, 2) == '\ x01 \ x00 \ x02 \ x00'. – aij

6

Par défaut, sur de nombreuses plates-formes, le court sera aligné sur un décalage multiple de 2, de sorte qu'il y aura un octet de remplissage ajouté après le caractère.

Pour désactiver cela, utilisez: struct.unpack("=BH", data). Cela utilisera l'alignement standard, ce qui ne correspond pas padding:

>>> struct.calcsize('=BH') 
3 

Le caractère = utilisera l'ordre des octets natif. Vous pouvez également utiliser < ou > au lieu de = pour forcer l'ordre des octets big-endian ou big-endian, respectivement.

+0

Bizarrement, je regarde mon dossier dans l'hexagone, et j'ai les données 01 01 00 qui montre trois octets pour la version: un seul octet « majeur » et un single 'mineur' court. Alors, la déclaration est-elle fausse? déballer ("BH", pack ("BH", 3, 6)) == (3, 6) Merci pour votre aide. –

+0

@ Thomas: Je ne suis pas sûr de ce que vous demandez exactement. L'expression que vous avez publiée sera évaluée à True. – interjay

+0

C'est ce que je pensais, et c'est à peu près ce que je fais. J'emballe, en utilisant Python, une base de données simple, avec pack ("BH", major_ver, minor_ver), puis décompresser en utilisant unpack ("BH"). Sur le même ordinateur qui est un Intel C2D x86-64. D'où vient l'octet supplémentaire?Je vais utiliser = BH, mais avec un soupçon qu'un octet est perdu ou gagné quelque part. –

Questions connexes