2010-08-18 6 views
2

Je lisais bien une bibliothèque de code python, et je suis déconcerté par cette déclaration:Que signifie% d dans struct.pack?

struct.pack("<ii%ds"%len(value), ParameterTypes.String, len(value), value.encode("UTF8")) 

Je comprends tout, mais %d, et je ne sais pas pourquoi la longueur de value est emballé deux fois .

Si je comprends bien, la structure aura peu de codage endian (<) et contiendra deux entiers (ii) suivi de% d, suivi d'une chaîne (s). Quelle est la signification de %d?

+0

La déclaration est en soi ** BUGGY *. Vois ma réponse. Quelle bibliothèque? -) –

+0

C'est une bibliothèque de fonctions écrites là où je travaille, pour traiter les messages envoyés sur un réseau. –

Répondre

1

Il est un string format ordinaire qui est utilisé pour créer le format struct

Essayez de le lire pour commencer comme une chaîne ordinaire (pour oublier struct le moment) ...

"<ii%ds" % len(value)

Si , par exemple, la longueur de la valeur itérable est 4 alors la chaîne sera, <ii4s. Il est ensuite passé à struct.pack prêt à emballer deux entiers suivi d'une chaîne de longueur quatre octets de la value itérables

+0

Merci! Je ne suis pas familier avec python, donc je n'ai pas réalisé que vous pouvez mettre en forme des chaînes comme ça. –

+0

@Matt Ellen: S'il vous plaît trouver un tutoriel. –

+0

@Brendan: -1; vois ma réponse. –

0

Le %d signifie que cela fonctionne en deux étapes.

Étape 1.

"<ii%ds"%len(value) 

crée la chaîne de mise en forme struct de "<ii...some number...s".

Étape 2.

La chaîne de mise en forme résultante est appliquée à trois valeurs

ParameterTypes.String, len(value), value.encode("UTF8") 
+0

-1 Voir ma réponse. –

+0

-1. Ne pense pas; enquêter. Sans un nombre signifie simplement que le nombre par défaut est de 1. Tends d'emballer correctement ??? Peut-être pensez-vous que struct.pack ("s", foo) fonctionne de la même manière que "% s"% foo? Ce n'est pas le cas; docs dit "" "Pour le caractère de format 's', le nombre est interprété comme la taille de la chaîne, pas comme un nombre de répétitions comme pour les autres caractères de format, par exemple, '10s' signifie une seule chaîne de 10 octets. '10c' signifie 10 caractères.Pour l'emballage, la chaîne est tronquée ou complétée avec des octets nuls comme approprié pour l'adapter."" " –

+0

@John Machin: Depuis que j'ai révisé ma réponse, je ne suis pas sûr que tout cela soit toujours pertinent, mais merci d'avoir signalé mon erreur flagrante –

0

Il est utilisé pour spécifier qu'une chaîne (value) de len(value) caractères doit être emballé après ces deux entiers.

Si, par exemple, value contenait "boo" alors le spécificateur de format réel pour pack serait "<ii3s".

0

L'importance de %d est qu'il est un paramètre de mise en forme pour les chaînes:
String Formatting Operations

Quand écorchée, "<ii%ds" % len(value) est un peu plus facile à comprendre. Il remplace l'indicateur de conversion% d dans la chaîne par la valeur de retour len(value), correctement classifié.

>>> str = "<ii%ds" 
>>> str % 5 
'<ii5s' 
>>> str % 3 
'<ii3s' 
2

Aarrrgh l'esprit rechigne ....

@ S. Lott: « » « Je ne pense pas que le nombre est particulièrement important, étant donné que Python aura tendance à emballer correctement sans elle. » » "-1. Ne pense pas; enquêter. Sans un nombre signifie simplement que le nombre par défaut est de 1. Tends d'emballer correctement ???Peut-être que vous pensez que struct.pack("s", foo) fonctionne de la même manière que "%s" % foo? Ce n'est pas le cas; docs say "" "Pour le caractère de format 's', le nombre est interprété comme la taille de la chaîne, pas comme un nombre de répétitions comme pour les autres caractères de format, par exemple, '10s' une chaîne de 10 octets, ., tandis que « 10c » signifie 10 caractères d'emballage, la chaîne de caractères est tronqué ou rembourré avec des octets nuls, le cas échéant pour l'adapter « » »

@Brendan:. -1. value n'est pas un tableau (quel qu'il soit); il est manifestement destiné à être une chaîne unicode ... regardez ici: value.encode("UTF8")

@Matt Ellen: La ligne de code que vous citez est sévèrement cassée. S'il y a des caractères non-ASCII dans value, les données seront perdues.

Brisons-le:

`struct.pack("<ii%ds"%len(value), ParameterTypes.String, len(value), value.encode("UTF8"))` 

Réduire l'espace de problème en supprimant le premier élément

struct.pack("<i%ds"%len(value), len(value), value.encode("UTF8"))

Maintenant, nous supposons que value est u'\xff\xff', donc len(value) est 2.

Let v8 = value.encode('UTF8'), c'est-à-dire '\xc3\xbf\xc3\xbf'.

Notez que len(v8) est de 4. Est-ce que le penny baisse encore?

donc ce que nous avons maintenant est

struct.pack("<i2s", 2, v8)

Le numéro 2 est emballé comme 4 octets, 02 00 00 00. La chaîne de 4 octets v8 est TRUNCATED (de la longueur 2 dans "2s") à la longueur deux. PERTE DE DONNÉES. ÉCHOUER.

La bonne façon de faire ce qui est sans doute voulu est:

v8 = value.encode('UTF8') 
struct.pack("<ii%ds" % len(v8), ParameterTypes.String, len(v8), v8) 
+0

Merci John, c'est très instructif. la personne qui a écrit la bibliothèque. (Mon patron, * gulp *) –