使用sys.settrace可以完成哪些很酷的黑客攻击?

Geo*_*Geo 22 python

我喜欢能够修改发送到函数的参数,使用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)
Run Code Online (Sandbox Code Playgroud)

这将打印:

1
1
3
3
5
Run Code Online (Sandbox Code Playgroud)

你还可以使用其他很酷的东西settrace吗?

Ned*_*der 24

我强烈建议不要滥用settrace.我假设你理解这些东西,但后来出现的其他人可能不会.有几个原因:

  1. Settrace是一个非常生硬的工具.OP的示例很简单,但实际上没有办法扩展它以用于实际系统.

  2. 这很神秘.任何来看你的代码的人都会完全不知道为什么它正在做它正在做的事情.

  3. 这很慢.为执行的每一行Python调用Python函数会使程序减慢许多倍.

  4. 这通常是不必要的.这里的原始示例可以通过其他几种方式完成(修改函数,在装饰器中包装函数,通过另一个函数调用它等),其中任何一个都比settrace更好.

  5. 很难做对.在原始示例中,如果您没有直接调用f,而是调用名为f的g,则跟踪函数将无法完成其工作,因为您从跟踪函数返回None,因此它只被调用一次然后被遗忘.

  6. 这将使其他工具无法工作.这个程序不可调试(因为调试器使用settrace),它不可追溯,无法测量其代码覆盖率等.部分原因是由于Python实现者缺乏远见:它们给了我们settrace但没有gettrace,所以很难有两个一起工作的跟踪功能.

跟踪功能可以实现酷炫的黑客攻击.能够滥用它很有趣,但请不要将它用于真实的东西.如果我听起来很糟糕,我道歉,但这是在真实的代码中完成的,这很痛苦.例如,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
Run Code Online (Sandbox Code Playgroud)

一个巧妙的黑客,但不幸的是,这意味着任何使用DecoratorTools的代码都无法使用coverage.py(或调试器,我猜).如果你问我,不是一个很好的权衡.我更改了coverage.py以提供一种模式,让它可以与DecoratorTools一起使用,但我希望我不必这样做.

即使标准库中的代码有时也会出错.Pyexpat决定与其他扩展模块不同,并调用跟踪函数,就好像它是Python代码一样.太糟糕了,他们做得不好.

</咆哮>


gak*_*gak 20

我创建了一个模块pycallgraph,用于生成调用图sys.settrace().


Ned*_*der 10

当然,代码覆盖是通过跟踪功能完成的.我们以前从未有过的一个很酷的事情是分支覆盖测量,并且即将发布,即将在alpha版本的coverage.py中发布.

例如,考虑这个功能:

def foo(x):
    if x:
        y = 10
    return y
Run Code Online (Sandbox Code Playgroud)

如果您使用此调用进行测试:

assert foo(1) == 10
Run Code Online (Sandbox Code Playgroud)

语句覆盖将告诉您函数的所有行都已执行.但是,当然,该函数中存在一个简单的问题:用0调用它会引发UnboundLocalError.

分支测量会告诉您代码中有一个未完全运用的分支,因为分支中只有一个分支被占用.