Отладка кода Python - PullRequest
       11

Отладка кода Python

0 голосов
/ 31 мая 2009

Редактировать: Вы можете получить полный источник здесь: http://pastebin.com/m26693

Снова отредактируйте: я добавил несколько бликов на страницу для вставки. 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. В точке, где это печатается, создается список аргументов для передачи плагину (Плагины - это просто команды в интерпретаторе выражений. Большая часть этого кода является интерпретатором выражений.) Список единственное представление экземпляра RESULT, которое следует за argc, является списком аргументов. Следующая строка - это список аргументов, когда он достигает вызываемого метода Python. Обратите внимание, что на этом этапе есть два аргумента. Первый из этих двух - мусор. Второй - то, что я хотел. Однако, как вы можете видеть в строках, начинающихся с «argc 1», этот список аргументов всегда имеет ширину 1 RESULT. Откуда исходит беспризорный аргумент?

Как я уже сказал, на выходе есть 3 деления. Первый дивизион сам по себе класс. Второе подразделение является подклассовым классом. И третье деление вообще не класс / экземпляр. Единственное подразделение, которое выводит то, что я ожидал, это третье. Обратите внимание, что у него есть 1 аргумент-член как до вызова, так и внутри вызова, а последняя строка является предполагаемым выводом. Он просто повторяет / возвращает аргумент "bar".

Есть ли какие-то особенности со списками переменных аргументов, о которых мне следует знать? Я имею в виду следующее:

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

Я действительно думаю, что ошибка как-то связана с этим, потому что именно отсюда, кажется, происходит мусор - между вызовом и прибытием выполнения в методе.

Редактировать: Хорошо, поэтому они ограничивают размер этих вопросов. :) Я сделаю все возможное, чтобы показать, что происходит. Вот соответствующая часть 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 ]

2 голосов
/ 31 мая 2009

Похоже, что ваш код был усечен, поэтому я не могу просмотреть его.

Учитывая, что вы получаете дополнительный аргумент только для методов, определенных в классе, может ли это быть переменная self? Каждый метод в классе Python получает self в качестве первого параметра, и если вы его не учтете, вы ошибетесь.

Другими словами, если это:

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

на самом деле это:

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

Если это так, то значение, традиционно удерживаемое self, будет присвоено result, а ваше значение результата будет в первой позиции argv.

Если это не так, вам нужно дать больше кода. По крайней мере, код, который фактически выполняет тесты.

1 голос
/ 31 мая 2009

В классе 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 в качестве первого аргумента функции. Я думаю, что вы можете объявить foo следующим образом:


class Foo:
    def __init__(self, visitor):
        visitor.AddFunction("foo", -1, self.foo)
    def foo(self, tree, result, *argv):
        print argv
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...