python settrace for for循环

时间:2012-10-21 15:52:05

标签: python debugging for-loop

我对跟踪for循环的执行感兴趣。具体来说,我想在for循环退出时向屏幕打印一条消息。 cavait是我无法控制for循环,也就是说,其他人将通过我的代码将for循环传递给trace。以下是一些示例代码:

import sys
import linecache           

def trace_calls(frame, event, arg): 
    if event != 'call':    
        return             
    co = frame.f_code      
    func_name = co.co_name 
    if func_name == 'write':
        return             
    return trace_lines

def trace_lines(frame, event, arg): 
    if event != 'line':
        return
    co = frame.f_code
    line_no = frame.f_lineno
    filename = co.co_filename
    print("%d %s"%(line_no, linecache.getline(filename, line_no)[:-1]))

def some_elses_code():
    j = 0
    for i in xrange(0,5):
       j = j + i
    return j

if __name__ == "__main__":
    sys.settrace(trace_calls)
    some_elses_code()

代码的输出:

22     j = 0
23     for i in xrange(0,5):
24         j = j + i
23     for i in xrange(0,5):
24         j = j + i
23     for i in xrange(0,5):
24         j = j + i
23     for i in xrange(0,5):
24         j = j + i
23     for i in xrange(0,5):
24         j = j + i
23     for i in xrange(0,5):
25     return j

我知道我可以查看行号,看看已执行的行不是下一行,但感觉不对。我想检查传递给trace_lines方法的框架对象,并看到for循环中使用的迭代器没有更多的项目。 This link表示for循环捕获异常,然后它知道迭代器全部用完了,但是我无法看到框架对象上填充的任何异常对象(即frame.f_exc_value始终为None) 。此外,我看到我的本地范围中没有var,它是for循环中使用的迭代器。这样的事情可能吗?

1 个答案:

答案 0 :(得分:2)

for循环创建的迭代器对循环是私有的,并且GET_ITERleft there每次执行{{picked up时都保留在Python堆栈上。 1}} - 这就是为什么你没有在当地人中看到它。

FOR_ITER通过捕获迭代器引发的FOR_ITER来终止循环,但这是由directly checking whether tp_iternext returned NULL测试的,所以在它有机会传播到异常之前捕获并清除异常一个Python框架。但即使你有权访问迭代器,也几乎无法使用它,因为Python迭代器不支持偷看。

由于Python的跟踪机制在输入或离开StopIteration块时没有调用跟踪回调,因此看起来您需要求助于诸如处理for事件之类的黑客来查找循环退出。