我对跟踪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循环中使用的迭代器。这样的事情可能吗?
答案 0 :(得分:2)
由for
循环创建的迭代器对循环是私有的,并且GET_ITER
和left there每次执行{{picked up时都保留在Python堆栈上。 1}} - 这就是为什么你没有在当地人中看到它。
FOR_ITER
通过捕获迭代器引发的FOR_ITER
来终止循环,但这是由directly checking whether tp_iternext
returned NULL
测试的,所以在它有机会传播到异常之前捕获并清除异常一个Python框架。但即使你有权访问迭代器,也几乎无法使用它,因为Python迭代器不支持偷看。
由于Python的跟踪机制在输入或离开StopIteration
块时没有调用跟踪回调,因此看起来您需要求助于诸如处理for
事件之类的黑客来查找循环退出。