7
votes

Existe-t-il un moyen élégant d'utiliser la structure et NamedTuple au lieu de cela?

Je lis, je lis un fichier binaire composé d'enregistrements que dans C ressembleraient à ceci: xxx pré>

maintenant je suis capable de l'analyser dans un tuple avec 23 valeurs distinctes, mais Serait préférer si je pouvais utiliser nomméTuple code> pour combiner les 20 premiers octets dans code> texte code> et les trois octets restants dans index code>. Comment puis-je y parvenir? Fondamentalement au lieu d'un tuple de 23 valeurs, je préférerais avoir deux buples de valeurs de 20 et 3 de 20 et 3 respectivement et d'accéder à ceux-ci à l'aide d'un "nom naturel", c'est-à-dire au moyen de namedTuple code>. P> P> Je suis actuellement en train d'utiliser le format "20c3b" code> pour structure.unpack_from () code>. p>

Remarque: il existe de nombreux enregistrements consécutifs dans la chaîne lorsque J'appelle parse_text code>. P>


Mon code (dépouillé vers les pièces correspondantes): p>

#!/usr/bin/env python
import sys
import os
import struct
from collections import namedtuple

def parse_text(data):
    fmt = "20c3B"
    l = len(data)
    sz = struct.calcsize(fmt)
    num = l/sz
    if not num:
        print "ERROR: no records found."
        return
    print "Size of record %d - number %d" % (sz, num)
    #rec = namedtuple('rec', 'text index')
    empty = struct.unpack_from(fmt, data)
    # Loop through elements
    # ...

def main():
    if len(sys.argv) < 2:
        print "ERROR: need to give file with texts as argument."
        sys.exit(1)
    s = os.path.getsize(sys.argv[1])
    f = open(sys.argv[1])
    try:
        data = f.read(s)
        parse_text(data)
    finally:
        f.close()

if __name__ == "__main__":
    main()


1 commentaires

data = str () (dans principal ) est inutile.


3 Réponses :


3
votes

Pourquoi ne pas avoir parse_text Utiliser la tranche de chaîne (données [: 20], données [20:]) pour attirer les deux valeurs, puis traiter chacun avec la structure?

ou prendre les 23 valeurs et les couper en deux?

Je dois manquer quelque chose. Peut-être souhaiterez-vous que cela se produise via le module de structure?


4 commentaires

+1. Les données de chaîne sont là dans Data et il est trivial pour utiliser la tranchée pour sortir les deux chaînes de longueur fixe; Il n'est pas nécessaire d'utiliser struct.unpack_from () pour obtenir des chaînes d'une chaîne. struct est extrêmement précieux pour décompresser les valeurs entier et flotter, mais ici, nous avons juste des chaînes.


@steveha: Je n'ai pas besoin débalk_from même si je veux utiliser le décalage ? Rappelez-vous que c'est un exemple que j'ai réduit.


@ user1277476: la chaîne contient des enregistrements num (voir le code). C'est pourquoi j'utilisais débalk_from en premier lieu. Bien sûr, la tranchée fonctionnerait également. Merci.


En fait, vous pouvez également utiliser struct si vous utilisez simplement "20s" au lieu de "20c" . Ensuite, vous obtenez une chaîne de longueur-20. Pourrait aussi bien faire cela au lieu de trancher. J'ai posté une réponse mais je vais le modifier pour le faire.



6
votes

Selon les documents: http://docs.python.org/library/struct.html

Les champs non déballés peuvent être nommés en les attribuant à des variables ou en enveloppant le résultat dans un tuple nommé: P> blockQuote> xxx pré>

donc dans votre cas p> xxx pré>

trancher les variables de déballage peut-être un problème, si le format était FMT = "20Si" code> ou quelque chose standard où nous ne retournons pas d'octets séquentiels, nous n'aurions pas besoin de le faire. P>

>>> import struct
>>> from collections import namedtuple
>>> data = "1"*24
>>> fmt = "20si"
>>> Rec = namedtuple('Rec', 'text index') 
>>> r = Rec._make(struct.unpack_from(fmt, data))
>>> r
Rec(text='11111111111111111111', index=825307441)
>>>


3 commentaires

AAAH, voir ... L'utilisation créative de la tranchée dans le _make appelait ce que j'avais manqué. Merci un tas. Je suivais les documents jusqu'à ce point, mais je n'ai pas compris comment faire cela sans variables supplémentaires. Je vais accepter dès que je peux, mais je ne peux pas uppoter avant minuit (épuisé tous les votes :)).


@ 0XC0000022L Pas de problème, bien que ce soit une douleur à trancher à cause des frais généraux, mais que je donne, je ne sais pas grand chose de votre situation, ce qui est le meilleur que je puisse trouver.


@Karlknechtel ouais je sais mais c'est dans les docs, et leur officiel donc je ne sais pas ...



3
votes

Voici ma réponse. Je l'ai d'abord écrit à l'aide de la tranchée au lieu de structure.unpack () mais @ samy.vilar a souligné que nous pouvons simplement utiliser le format "S" pour obtenir la chaîne. (J'aurais dû me rappeler que!)

Cette réponse utilise structure.unpack () deux fois: une fois pour obtenir les chaînes, et une fois pour déballer la deuxième chaîne comme un entier.

Je ne suis pas sûr de ce que vous voulez faire avec le "3b" article, mais je suppose que vous voulez décompresser cela comme un entier 24 bits. J'ai ajouté un 0 octet à la fin de la chaîne 3-Char et déballé comme un entier, au cas où vous voulez que vous voulez.

légèrement difficile: la ligne comme n, = struct.unpack (...) déballe une longueur-1 tuple dans une variable. En Python, la virgule fait le tuple, donc avec une virgule après un nom, nous utilisons le déballage de tuple pour déballer une longueur-1 tuple dans une seule variable.

aussi, nous pouvons utiliser un avec Pour ouvrir le fichier, qui élimine le besoin du bloc . Nous pouvons également simplement utiliser f.fin () pour lire le fichier entier en une fois, sans avoir à calculer la taille du fichier. xxx < / p>


2 commentaires

Merci, cette réponse a des concepts que j'ai lus dans le livre (apprentissage de Python) mais je ne me suis pas encore utilisé à peine.


Merci encore. Cette solution est brillante, en particulier la partie avec décodage de l'entier. Merci pour ça. Comme ma question était différente (dû, en partie, faute de connaissances), je pense que ce serait injuste accepter cette réponse. Cependant, j'ai activement tamisée à travers des autres réponses liées au Python et j'ai dépensé une partie de mon quota de vote quotidien. Merci encore!