2012-10-21 31 views
1

我有兴趣追踪for循环的执行情况。具体来说,我想在for循环退出时在屏幕上显示一条消息。 cavait是我无法控制for循环,也就是说,其他人将通过我的代码循环追踪。下面是一些示例代码:python settrace a for循环

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循环中使用的迭代器。是这样的可能吗?

+0

使用诸如'pudb'等调试器是一种选择吗? – arturhoo

+0

我不这样。从简单的看pudb是什么,它看起来非常类似于pdb,但有一个更好的gui。我对单步代码执行/调试不感兴趣,但是钩住代码执行,并显示发生的事件。我可能错在pudb提供的东西上,所以请纠正我。 – karlw

回答

2

for环产生的迭代器是私有的循环,最终由的FOR_ITER每次执行首位,而其为什么你没有看到它当地人保持Python的堆栈,left there通过GET_ITERpicked up

FOR_ITER确实终止通过捕捉StopIteration由迭代提出的循环,而这是由directly checking whether tp_iternext returned NULL测试,所以异常被捕获并清除它得到一个机会传播到一个Python框架之前。但即使你有权访问迭代器,也很少有人能够使用它,因为Python迭代器不支持窥视。

由于Python的跟踪机制在for块输入或离开时不会调用跟踪回调,因此看起来您需要采取诸如处理line事件的黑客手段来发现该回路已退出。

+0

很棒的回答。我将要走下“诸如加工线事件之类的黑客”路线。 – karlw

+0

你能在这里看看我的问题吗?https://stackoverflow.com/questions/30770628/how-can-i-tell-if-a-function-is-called-in-a-loop-within-pythons -tracer功能 – NeoWang