Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

unpack erreur

7 réponses
Avatar
Pierrot
Bonjour,
J'essaie de depacker la chaîne suivante:

data = 80 * 'e'

Avec le formattage suivant tout va bien:
tempo = unpack('i i c 3c 17i',data)

Avec celui-ci j'ai l'erreur suivante:
tempo = unpack('i c i 3c 17i',data)

struct.error: unpack str size does not match format

Qu'est que ne colle pas ? Merci pour votre aide.

7 réponses

Avatar
jean-michel bain-cornu
Bonjour,
Pierrot wrote:
Bonjour,
J'essaie de depacker la chaîne suivante:

data = 80 * 'e'

Avec le formattage suivant tout va bien:
tempo = unpack('i i c 3c 17i',data)

Avec celui-ci j'ai l'erreur suivante:
tempo = unpack('i c i 3c 17i',data)

struct.error: unpack str size does not match format

Qu'est que ne colle pas ? Merci pour votre aide.


D'après mon interprétation, c'est à cause d'un mauvais alignement en
mémoire.
Tu es sur une machine 32 bits. Chaque entier (i) prends 4 octets et
seulement 4. Chaque caractère (c) prends 1 octet et seulement 1 (sauf en
unicode, ce qui est HS ici).
Dans le premier cas 'tempo = unpack('i i c 3c 17i',data)', le groupe 'c
3c' fait bien 32 bits (4 octets). Le groupe '17i' peux donc commencer
sur un bloc mémoire cohérent de 32 bits. Tout va bien.
Dans le deuxième cas 'tempo = unpack('i c i 3c 17i',data)', le deuxième
groupe 'c' ne fait qu'un octet, et ne termine pas le bloc de 32 bits,
dont 3 octets ne sont pas utilisés. Le groupe 'i' suivant commençant sur
le bloc de 32 bits suivant, data n'est pas assez long pour terminer
l'extraction, ça plante.
Par exemple, 'tempo = unpack('i c c c c i 3c 16i',data)' marche très
bien. On peut faire aussi 'tempo = unpack('i c i 3c 16i',data)', mais ce
n'est pas rigoureux.
Sur une machine 64 bits, il faut compter 8 octets pour un entier (je te
laisse calculer la taille de 'data' ;-)
Dis-moi si je ne suis pas clair.
A+
jm

Avatar
jean-michel bain-cornu
jean-michel bain-cornu wrote:
Bonjour,
Pierrot wrote:
data = 80 * 'e'
Tu es sur une machine 32 bits. Chaque entier (i) prends 4 octets et

seulement 4. Chaque caractère (c) prends 1 octet et seulement 1 (sauf en
unicode, ce qui est HS ici).
Après relecture, je me rends compte que ça n'a rien d'évident. Pourquoi

n'est-on pas en Unicode par défaut ?
Par ailleurs, pourquoi ai-je la même erreur qd je fais : data€*u'e',
ou même : data€*u'é' ? En effet, dans ce dernier cas, la taille
physique de la chaîne est de 160 caractères, ça devrait donc marcher !
De plus, pourquoi len(80*u'é') est-il égal à len(80*u'a') ?
Si qqun a des idées sur tout ça, je suis preneur.
A+
jm


Avatar
tiissa

Bonjour,
J'essaie de depacker la chaîne suivante:

data = 80 * 'e'

Avec le formattage suivant tout va bien:
tempo = unpack('i i c 3c 17i',data)

Avec celui-ci j'ai l'erreur suivante:
tempo = unpack('i c i 3c 17i',data)

struct.error: unpack str size does not match format

Qu'est que ne colle pas ? Merci pour votre aide.


C'est juste une question d'alignement. Par defaut, il s'attend a
l'alignement natif du C. Dans celui-ci les entiers commencent a une
position multiple de 4 et pour cela il rajoute des octets bidons.
Ainsi :
data = '1234e'
struct.unpack('i c', data)
(875770417, 'e')



struct.unpack('c i ', data)
Traceback (most recent call last):



File "<stdin>", line 1, in ?
struct.error: unpack str size does not match format
data2 = 'eccc1234'
struct.unpack('c i', data2)
('e', 875770417)








On voit ici que les 'ccc' ont ete ignores et ne servaient qu'a
l'alignement de l'entier represente par '1234'.

Ce que tu peux faire c'est changer le comportement vis-a-vis de
l'alignement (voir [1]) :

struct.unpack('=c i ', data)
('1', 1697919794)









[1] http://docs.python.org/lib/module-struct.html



Avatar
Christophe
jean-michel bain-cornu wrote:

Bonjour,
Pierrot wrote:

data = 80 * 'e'


Tu es sur une machine 32 bits. Chaque entier (i) prends 4 octets et
seulement 4. Chaque caractère (c) prends 1 octet et seulement 1 (sauf
en unicode, ce qui est HS ici).


Après relecture, je me rends compte que ça n'a rien d'évident. Pourquoi
n'est-on pas en Unicode par défaut ?
Par ailleurs, pourquoi ai-je la même erreur qd je fais : data€*u'e',
ou même : data€*u'é' ? En effet, dans ce dernier cas, la taille
physique de la chaîne est de 160 caractères, ça devrait donc marcher !
De plus, pourquoi len(80*u'é') est-il égal à len(80*u'a') ?


C'est comme si tu disais : pourquoi len(80*u'a') == len(80*u'b'). Ne pas
confondre encodage et Unicode ! Unicode is not UTF-8 !

Si qqun a des idées sur tout ça, je suis preneur.
A+
jm




Avatar
Christophe
jean-michel bain-cornu wrote:

Bonjour,
Pierrot wrote:

data = 80 * 'e'


Tu es sur une machine 32 bits. Chaque entier (i) prends 4 octets et
seulement 4. Chaque caractère (c) prends 1 octet et seulement 1 (sauf
en unicode, ce qui est HS ici).


Après relecture, je me rends compte que ça n'a rien d'évident. Pourquoi
n'est-on pas en Unicode par défaut ?
Par ailleurs, pourquoi ai-je la même erreur qd je fais : data€*u'e',
ou même : data€*u'é' ? En effet, dans ce dernier cas, la taille
physique de la chaîne est de 160 caractères


J'ai oublié de répondre à ça. La taille physique d'une chaine unicode
est implementation dependant. Il est interdit d'en parler ou de la
manipuler. De plus, elle serait plutôt égale à 320 ( 4 octets par
caractères unicode ) normalement. Il est donc "interdit" de manipuler la
représentation physique d'une chaine unicode.

, ça devrait donc marcher !
De plus, pourquoi len(80*u'é') est-il égal à len(80*u'a') ?
Si qqun a des idées sur tout ça, je suis preneur.
A+
jm




Avatar
Pierrot

Bonjour,
J'essaie de depacker la chaîne suivante:

data = 80 * 'e'

Avec le formattage suivant tout va bien:
tempo = unpack('i i c 3c 17i',data)

Avec celui-ci j'ai l'erreur suivante:
tempo = unpack('i c i 3c 17i',data)

struct.error: unpack str size does not match format

Qu'est que ne colle pas ? Merci pour votre aide.


C'est juste une question d'alignement. Par defaut, il s'attend a
l'alignement natif du C. Dans celui-ci les entiers commencent a une
position multiple de 4 et pour cela il rajoute des octets bidons.
Ainsi :
data = '1234e'
struct.unpack('i c', data)
(875770417, 'e')



struct.unpack('c i ', data)
Traceback (most recent call last):



File "<stdin>", line 1, in ?
struct.error: unpack str size does not match format
data2 = 'eccc1234'
struct.unpack('c i', data2)
('e', 875770417)




On voit ici que les 'ccc' ont ete ignores et ne servaient qu'a
l'alignement de l'entier represente par '1234'.

Ce que tu peux faire c'est changer le comportement vis-a-vis de
l'alignement (voir [1]) :

struct.unpack('=c i ', data)
('1', 1697919794)





[1] http://docs.python.org/lib/module-struct.html

Merci , c'est exactement ce que je cherchais.





Avatar
jean-michel bain-cornu
Christophe wrote:

jean-michel bain-cornu wrote:

Bonjour,
Pierrot wrote:

data = 80 * 'e'



Tu es sur une machine 32 bits. Chaque entier (i) prends 4 octets et
seulement 4. Chaque caractère (c) prends 1 octet et seulement 1 (sauf
en unicode, ce qui est HS ici).



Après relecture, je me rends compte que ça n'a rien d'évident.
Pourquoi n'est-on pas en Unicode par défaut ?
Par ailleurs, pourquoi ai-je la même erreur qd je fais : data€*u'e',
ou même : data€*u'é' ? En effet, dans ce dernier cas, la taille
physique de la chaîne est de 160 caractères



J'ai oublié de répondre à ça. La taille physique d'une chaine unicode
est implementation dependant. Il est interdit d'en parler ou de la
manipuler. De plus, elle serait plutôt égale à 320 ( 4 octets par
caractères unicode ) normalement. Il est donc "interdit" de manipuler la
représentation physique d'une chaine unicode.
Ma confusion vient du fait que lors du unpack on raisonne en positions

binaires, alors que lorsqu'on manipule des strings on raisonne en
caractères. Peut-être serait-ils plus sûr d'utiliser des array lorsqu'on
fait ce genre d'opération ?
Après essai le comportement semble être le même avec les array. Ainsi,
unpack('ii',array('c','ééééeeee')) donne la même chose que
unpack('ii','ééééeeee') : (-370546199, 1701143909).
Je vois bien à quoi correspond 1701143909 (0x65656565, soit la
représentation de 'eeee'), mais d'ou sort la valeur -370546199 ? En
hexa, ça donne FFFFFFFFE9E9E9E9. Sachant que la représentation de 'é'
est 'xe9', soit E9 en hexa, je ne comprends pas très bien la logique de
la valeur -370546199 !
Cela dit, ya pas mort d'homme, c'est juste pour essayer de comprendre...