2009-05-31 8 views
0

Edit: Vous pouvez obtenir la source complète ici: http://pastebin.com/m26693débogage du code Python

Modifier à nouveau: j'ai ajouté quelques points saillants à la page Pastebin. Je vais probablement regretter de poser une si longue question, mais je suis perplexe avec ce bug et je pourrais utiliser quelques conseils. Vous allez devoir exécuter ce code (edit: plus maintenant, je ne pourrais pas inclure tout le code - il a été tronqué) pour vous aider à vraiment voir ce qui se passe, sauf si vous êtes Dieu ou quelque chose, alors par tous les moyens le comprendre sans le courir. En fait, j'espère que je pourrai l'expliquer assez bien pour que ce ne soit pas nécessaire, et je m'excuse si je ne le fais pas.

D'abord, je vais vous donner quelques résultats. (Edit: Il y a une nouvelle sortie ci-dessous)

argc 1 [<__main__.RESULT instance at 0x94f91ec>] 
(<__main__.RESULT instance at 0x9371f8c>, <__main__.RESULT instance at 0x94f91ec>) 
None 
bar 
internal error: unknown result type 0 
argc 1 [<__main__.RESULT instance at 0x94f92ac>] 
(<__main__.RESULT instance at 0x94f91ac>, <__main__.RESULT instance at 0x94f92ac>) 
None 
bar 
internal error: unknown result type 0 
argc 1 [<__main__.RESULT instance at 0x94f91ec>] 
(<__main__.RESULT instance at 0x94f91ec>,) 
String: 'bar' 

Nous avons 3 divisions dans la sortie. Notez que argc est toujours 1. Au point où cela est imprimé, une liste d'arguments a été construite pour être passée à un plugin (les plugins sont simplement des commandes dans l'interpréteur d'expression, la plus grande partie de ce code est l'interpréteur d'expression). une seule représentation d'instance RESULT qui suit argc est la liste d'arguments. La ligne suivante est la liste des arguments une fois qu'elle atteint la méthode Python appelée. Notez qu'il a deux arguments à ce stade. Le premier de ces deux est poubelle. Le deuxième est ce que je voulais. Cependant, comme vous pouvez le voir sur les lignes commençant par "argc 1" cette liste d'arguments est toujours 1 RESULT large. D'où vient l'argument parasite?

Comme je l'ai dit, il y a 3 divisions dans la sortie. La première division est une classe à part. La deuxième division est une classe sous-classée. Et la troisième division n'est pas une classe/instance du tout. La seule division qui produit ce que j'attendais est la 3ème. Notez qu'il a 1 argument membre avant l'appel et dans l'appel, et la dernière ligne est la sortie prévue. Il fait simplement écho/retourne l'argument "bar".

Y a-t-il des particularités avec des listes d'arguments variables dont je devrais être conscient? Ce que je veux dire est la suivante:

def foo(result, *argv): 
    print argv[0] 

Je pense vraiment que le bug a quelque chose à voir avec cela, parce que c'est là la poubelle semble provenir de - entre l'appel et l'arrivée d'exécution dans la méthode.

Modifier: Ok, ils limitent donc la taille de ces questions. :) Je ferai de mon mieux pour montrer ce qui se passe. Voici la partie pertinente d'EvalTree. Notez qu'il n'y a que 2 divisions dans ce code. J'ai foiré cet autre fichier et l'ai supprimé.

def EvalTree(self, Root): 
    type = -1 
    number = 0.0 
    freeme = 0 


    if Root.Token == T_NUMBER or Root.Token == T_STRING: 
     return 0 

    elif Root.Token == T_VARIABLE: 
     self.CopyResult(Root.Result, Root.Variable.value) 
     return 0 

    elif Root.Token == T_FUNCTION: 
     argc = Root.Children 
     param = resizeList([], argc, RESULT) 
     print "argc", argc 
     for i in range(argc): 
      self.EvalTree(Root.Child[i]) 
      param[i] = Root.Child[i].Result 

     self.DelResult(Root.Result) 
     Root.Function.func(Root.Result, *param) # I should have never ever programmed Lua ever. 
     return 0 

Voici la classe du plugin.

class Foo: 
    def __init__(self, visitor): 
     visitor.AddFunction("foo", -1, self.foo) 
    def foo(self, result, *argv): 
     print argv 

Ici, tout est exécuté.

if __name__ == "__main__": 
    evaluator = Evaluator() 

    expression = "foo2('bar')" 
    #expression = "uptime('test')" 
    evaluator.SetVariableString("test", "Foo") 
    def func(self, result, *arg1): 
     print arg1 
     evaluator.SetResult(result, R_STRING, evaluator.R2S(arg1[0])) 

    evaluator.AddFunction('foo2', -1, func) 

    result = RESULT(0, 0, 0, None) 
    tree = evaluator.Compile(expression) 
    if tree != -1: 
     evaluator.Eval(tree, result) 
     if result.type == R_NUMBER: 
      print "Number: %g" % (evaluator.R2N(result)) 
     elif result.type == R_STRING: 
      print "String: '%s'" % (result.string) #(evaluator.R2S(result)) 
     elif result.type == (R_NUMBER | R_STRING): 
      print "String: '%s' Number: (%g)" % (evaluator.R2S(result), evaluator.R2N(result)) 
     else: 
      print "internal error: unknown result type %d" % (result.type) 

    expression = "foo('test')" 
     result = RESULT(0, 0, 0, None) 
     tree = evaluator.Compile(expression) 
     if tree != -1: 
       evaluator.Eval(tree, result) 
       if result.type == R_NUMBER: 
         print "Number: %g" % (evaluator.R2N(result)) 
       elif result.type == R_STRING: 
         print "String: '%s'" % (result.string) #(evaluator.R2S(result)) 
       elif result.type == (R_NUMBER | R_STRING): 
         print "String: '%s' Number: (%g)" % (evaluator.R2S(result), evaluator.R2N(result)) 
       else: 
         print "internal error: unknown result type %d" % (result.type) 

Ceci est la nouvelle sortie:

argc 1 
(<__main__.RESULT instance at 0x9ffcf4c>,) 
String: 'bar' 
argc 1 
(<__main__.RESULT instance at 0xa0030cc>, <__main__.RESULT instance at 0xa0030ec>) 
internal error: unknown result type 0 
+0

Trop fatigué pour faire plus qu'écraser ceci maintenant. Vous voudrez peut-être ajouter dans le paragraphe introductif qui énonce plus clairement le problème que vous essayez de résoudre. Tels que: Je reçois une sortie de "XYZ" de la fonction fizzBat et je veux obtenir une sortie de "ABC". Je pense que vous avez la plus grande partie de cela, mais ce n'est pas immédiatement évident. Vous pouvez obtenir plus d'aide si vous pouvez clarifier le problème et réduire la portée du code source que nous devons examiner. Si personne d'autre n'a résolu cela pour vous, je pourrais revenir et essayer d'être plus utile après avoir dormi ... –

+0

J'ai essayé d'en ajouter plus, mais je ne peux pas penser à autre chose à couvrir. Si je pense à plus, je vais l'ajouter. – Scott

+0

Pourquoi ne mettez-vous pas tout le code ici http://pastebin.com/ et publiez un lien dessus. –

Répondre

2

Il semble que votre code a été tronqué, donc je ne peux pas regarder à travers.

Étant donné que vous obtenez uniquement l'argument supplémentaire sur les méthodes définies dans une classe, peut-être la variable self?Chaque méthode sur une classe Python reçoit self en tant que premier paramètre, et si vous ne le comptez pas, vous obtiendrez des erreurs.

En d'autres termes, si cela:

def foo(result, *argv): 
    print argv[0] 

être en fait ceci:

def foo(self, result, *argv): 
    print argv[0] 

Si oui, alors la valeur traditionnellement détenue par self sera affecté à result, et votre valeur de résultat sera être en première position de argv.

Si ce n'est pas le cas, vous devrez donner plus de code. À tout le moins, le code qui exécute réellement les tests.

+0

Ok, je l'ai mis à jour avec le code correspondant. – Scott

+0

J'ai réfléchi à votre réponse. Si tel était le cas, vous verriez une instance d'instances d'évaluateur et de résultat au lieu de RESULT et RESULT. Je suis d'accord cependant, le fait que le bug ne se produit que lorsque vous travaillez avec des méthodes d'instance suggère qu'il peut avoir quelque chose à voir avec soi. Je ne peux pas le trouver. – Scott

+0

J'ai mal compris certains de vos mots. Je comprends maintenant, et vous aviez raison. – Scott

1

En classe Foo, lorsque vous appelez


    def __init__(self, visitor): 
     visitor.AddFunction("foo", -1, self.foo) 

... vous ajoutez ce qu'on appelle un argument de méthode "lié" (qui est, self.foo). C'est comme une fonction qui a déjà l'argument self spécifié. La raison en est, lorsque vous appelez self.foo (bar, baz), vous ne spécifiez plus "self" dans la liste des arguments. Si vous appelez


    def __init__(self, visitor): 
     visitor.AddFunction("foo", -1, Foo.foo) 

... vous obtiendrez le même résultat que votre fonction libre. Cependant, je ne pense pas que ce soit tout à fait ce que vous voulez. En outre, EvalTree passe son propre self comme premier arg à la fonction. Je pense que ce que vous pourriez vouloir est de déclarer foo comme ceci:


class Foo: 
    def __init__(self, visitor): 
     visitor.AddFunction("foo", -1, self.foo) 
    def foo(self, tree, result, *argv): 
     print argv 
+0

"En outre, EvalTree se transmet en tant que premier arg à la fonction." - C'était mon problème. J'ai pris l'habitude de tout passer à Lua en jouant à WoW et je me suis tapé moi-même. Cela n'aurait pas dû être le soi passé comme premier argument. Je le sais. Je ne peux pas croire que je ne l'ai pas vu. En tout cas, ça marche maintenant. Merci d'avoir regardé cela et d'avoir répondu. – Scott

Questions connexes