2012-10-21 39 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