调试一些Python代码

时间:2009-05-31 03:47:57

标签: python debugging

修改:您可以在此处获取完整的来源: http://pastebin.com/m26693

再次编辑:我在pastebin页面添加了一些亮点。 http://pastebin.com/m10f8d239

我可能会后悔问这么长的问题,但我对这个错误感到困惑,我可以使用一些指导。您将不得不运行此代码(编辑:不再。我不能包含所有代码 - 它被截断)以帮助真正看到发生了什么,除非您是上帝或其他什么,然后通过各种方式计算出来而不运行它。实际上我希望我能够很好地解释它,所以没有必要,如果我没有做到这一点,我会道歉。

首先我会给你一些输出。 (编辑:下面有新的输出)

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'

我们在输出中有3个分区。请注意,argc始终为1.在打印的位置,构建了一个参数列表以传递给插件(插件只是表达式解释器中的命令。大部分代码都是表达式解释器。)列表跟随argc的单个RESULT实例表示是参数列表。一旦到达被调用的Python方法,下一行就是参数列表。请注意,此时它有两个参数。这两个中的第一个是垃圾。第二个是我想要的。但是,正如您在“argc 1”开头的行中所看到的那样,参数列表始终为1 RESULT wide。流浪的争论来自哪里?

就像我说的那样,输出中有3个分区。第一部分本身就是一个阶级。第二个分部是一个子类。第三部门根本就没有阶级/实例。输出我预期的唯一分区是第3分区。注意它在调用之前和调用中都有1个参数成员,最后一行是预期的输出。它只是回显/返回参数“bar”。

我应该注意变量参数列表是否有任何特殊之处?我的意思是:

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

我真的认为这个bug与此有关,因为这就是垃圾似乎来自 - 在调用和执行到达方法之间。

编辑:好的,所以他们限制了这些问题的大小。 :)我会尽我所能来展示正在发生的事情。这是EvalTree的相关部分。请注意,此代码中只有2个分区。我弄乱了其他文件并删除了它。

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

这是插件的类。

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

这就是全部执行的地方。

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)

这是新输出:

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

2 个答案:

答案 0 :(得分:2)

您的代码似乎被截断了,所以我无法查看它。

鉴于您只获得了类中定义的方法的额外参数,可能是self变量吗? Python类上的每个方法都接收self作为第一个参数,如果你不考虑它,你就会出错。

换句话说,应该这样:

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

实际上就是这样:

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

如果是这样,那么self传统上保留的值将被分配给result,您的结果值将位于argv的第一个位置。

如果不是这样,你需要提供更多代码。至少,实际运行测试的代码。

答案 1 :(得分:1)

在Foo课程中,当你打电话


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

...您正在添加所谓的“绑定”方法参数(即self.foo)。它就像一个已经指定了self参数的函数。原因是,当你调用self.foo(bar,baz)时,你不会在参数列表中再次指定“self”。如果你打电话


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

...你得到与你的免费功能相同的结果。但是,我认为这不是你想要的。此外,EvalTree将自己的self作为第一个arg传递给函数。我想你可能想要的是这样声明foo:


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