Какие интересные хаки можно сделать с помощью sys.settrace?

Мне нравится изменять аргументы, получаемые при отправке функции, используя settrace, например:

import sys

def trace_func(frame,event,arg):
    value = frame.f_locals["a"]
    if value % 2 == 0:
        value += 1
        frame.f_locals["a"] = value

def f(a):
    print a

if __name__ == "__main__":
    sys.settrace(trace_func)
    for i in range(0,5):
        f(i)

И это напечатает:

1
1
3
3
5

Какие еще интересные вещи вы можете использовать с помощью settrace?

Ответ 1

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

  • Settrace - очень тупой инструмент. Пример OP простой, но практически нет возможности расширить его для использования в реальной системе.

  • Это загадочно. Любой, кто придет посмотреть ваш код, будет полностью зациклен, почему он делает то, что он делает.

  • Это медленно. Вызов функции Python для каждой строки выполняемого Python приведет к замедлению вашей программы несколькими мультипликаторами.

  • Это обычно не нужно. Исходный пример здесь мог бы быть выполнен несколькими другими способами (изменить функцию, обернуть функцию в декораторе, вызвать ее через другую функцию и т.д.), Любой из которых был бы лучше, чем определение.

  • Трудно получить право. В исходном примере, если вы не вызывали f напрямую, а вместо этого называли g, который вызвал f, ваша функция трассировки не выполнила бы свою работу, потому что вы вернули None из функции trace, поэтому он только вызывается один раз и затем забывается.

  • Это позволит другим инструментам работать. Эта программа не будет отлаживаемой (потому что отладчики используют settrace), она не будет отслеживаться, она не сможет измерить ее охват кода и т.д. Частично это связано с отсутствием предвидения со стороны разработчиков Python: они дал нам оцепенение, но не gettrace, поэтому трудно иметь две функции слежения, которые работают вместе.

Функции трассировки делают классные хаки. Это весело, чтобы иметь возможность злоупотреблять им, но, пожалуйста, не используйте его для реальных вещей. Если я озвучу hectoring, я извиняюсь, но это было сделано в реальном коде, и это боль. Например, DecoratorTools использует функцию трассировки для выполнения магического умения сделать этот синтаксис в Python 2.3:

# Method decorator example
from peak.util.decorators import decorate

class Demo1(object):
    decorate(classmethod)   # equivalent to @classmethod
    def example(cls):
        print "hello from", cls

Утонченный взломать, но, к сожалению, это означало, что любой код, который использовал DecoratorTools, не работал бы с cover.py(или отладчиками, я думаю). Не очень хороший компромисс, если вы спросите меня. Я изменил cover.py, чтобы предоставить режим, который позволяет ему работать с DecoratorTools, но мне жаль, что мне не пришлось.

Даже обычный код в стандартной библиотеке иногда ошибочен. Pyexpat решил отличаться от любого другого модуля расширения и вызывать функцию трассировки, как если бы это был код Python. Жаль, что они сделали плохую работу.

</напыщенная >

Ответ 2

Я создал модуль под названием pycallgraph, который генерирует графики вызовов с помощью sys.settrace().

Ответ 3

Конечно, покрытие кода выполняется с помощью функции трассировки. Одна интересная вещь, которую мы не имели раньше, - это измерение охвата филиалом, и это происходит хорошо, вот-вот выйдет в альфа-версии coverage.py.

Так, например, рассмотрим эту функцию:

def foo(x):
    if x:
        y = 10
    return y

если вы проверите его с помощью этого вызова:

assert foo(1) == 10

тогда покрытие оператора скажет вам, что все строки функции выполнены. Но, конечно, в этой функции есть простая проблема: вызов ее с помощью 0 вызывает UnboundLocalError.

Измерение отрасли сообщит вам, что в коде, который не полностью задействован, есть ветвь, потому что только одна ветка ветки когда-либо берется.

Ответ 6

Отладчик python Pdb использует sys.settrace для анализа строк для отладки.

Здесь c оптимизация/расширение для pdb, которая также использует sys.settrace

https://bitbucket.org/jagguli/cpdb

Ответ 7

Одним из последних проектов, который интенсивно использует settrace является PySnooper

Это помогает новым программистам отслеживать/регистрировать/отслеживать результаты своих программ. Ура!