2010-08-27 5 views
1

Je crée un programme pour calculer la latence à partir d'un fichier tcpdump/pcap et je veux être en mesure de spécifier des règles sur la ligne de commande pour corréler les paquets - c'est-à-dire trouver le délai entre l'envoi d'une règle de correspondance de paquets A et la réception d'une règle de correspondance de paquets B (un exemple concret serait un FIX NewOrderSingle en cours d'envoi et un FIX ExecutionReport correspondant reçu).Créer une fonction python à l'exécution pour correspondre à un nombre variable d'entrées de dictionnaire

Voici un exemple des champs dans le paquet (avant qu'ils aient été convertis en forme de dictionnaire) - Je teste la version numérique du champ (entre parenthèses) plutôt que la version anglaise:

BeginString (8): FIX.4.2 
    BodyLength (9): 132 
    MsgType (35): D (ORDER SINGLE) 
    SenderCompID (49): XXXX 
    TargetCompID (56): EXCHANGE 
    MsgSeqNum (34): 1409104 
    SendingTime (52): 20100723-12:49:52.296 
    Side (54): 1 (BUY) 
    Symbol (55): A002 
    ClOrdID (11): BUY704552 
    OrderQty (38): 1000 
    OrdType (40): 2 (LIMIT) 
    Price (44): 130002 
    TimeInForce (59): 3 (IMMEDIATE OR CANCEL) 
    QuoteID (117): A002 
    RelatdSym (46): A002 
    CheckSum (10): 219 [correct]

Actuellement, j'ont les arguments qui sortent de la ligne de commande dans une liste imbriquée:

[[35, 'D'], [55, 'A002']] 

(où le premier élément de chaque sous-liste est le numéro de champ et la deuxième est la valeur)

J'ai essayé itérer sur cette liste de règles pour accumuler une expression lambda:

for field, value in args.send["fields_filter"]: 
    if matchers["send"] == None: 
     matchers["send"] = lambda fix : field in fix and fix[field] == value 
    else: 
     matchers["send"] = lambda fix : field in fix and fix[field] == value and matchers["send"](fix)

Quand je lance le programme cependant, je reçois la sortie:

RuntimeError: maximum recursion depth exceeded in cmp 

lambdas sont en retard contraignantes? Cela s'applique-t-il donc à tous les identifiants de l'expression ou seulement à ceux passés en arguments? Il semble que le premier est vrai

Quelle est la meilleure façon d'obtenir cette fonctionnalité? Je me sens comme je vais à ce sujet dans le mauvais sens actuellement. Peut-être que c'est une mauvaise utilisation des expressions lambda, mais je ne connais pas une meilleure alternative pour cela.

+0

Je ne suis pas sûr de ce que votre code essaie d'accomplir ... mais la dernière ligne ressemble à une fonction récursive classique. Vous affectez la fonction lambda à la touche 'send' des dictateurs dict donc mathers ['send'] (fix) est un appel récursif. Il n'y a pas de condition de fin, donc ça court juste jusqu'à ce qu'il fasse exploser la pile. Je ne peux pas dire si la conception de lambda est "bonne" ou pas mais ce problème particulier ressemble à un bogue d'implémentation typique. – Rakis

+0

@Rakis: Donc le genre de chose que j'essayais de compiler est le suivant: 35 in fix and fix[35] == "D" and (55 in fix and fix[55] == "A002") Les termes qui s'y trouvent dépendraient de ce qui sort de la ligne de commande. Voir la réponse de S. Lott qui résume ce que je veux. – davedavedave

Répondre

2

Ne pas utiliser lambdas. Ils sont liaison tardive. Peut-être que vous voulez un partial de functools, mais même cela semble trop complexe.

Vos données ont des noms de champs, des chiffres et des valeurs, n'est-ce pas?

Vos paramètres de ligne de commande utilisent des numéros de champ et des valeurs, n'est-ce pas?

Vous souhaitez un dictionnaire codé par numéro de champ. Dans ce cas, vous n'avez pas besoin de recherches complexes. Tu veux juste quelque chose comme ça.

def match(packet_dict, criteria_list): 
    t = [ packet_dict[f] == v for f,v in criteria_list ] 
    return any(t) 

Quelque chose comme ça devrait gérer tout pour vous.

+0

Merci pour la suggestion de partielle, je le regarde.J'essayais d'éviter de faire une itération à chaque fois que je courais contre des vidages de millions de paquets et j'ai pensé que générer une sorte de fonction de correspondance au début et appeler à chaque fois serait beaucoup plus efficace. Je vais essayer et voir comment il se comporte bien. – davedavedave

+0

@davedavedave: Un partiel ne va pas aider beaucoup. La recherche hashed du dictionnaire est instantanée. La boucle de critères est petite avec remarquablement peu de frais généraux. –

Questions connexes