2017-03-21 23 views
2

在試圖回答另一個問題時,我發現在理論上應該沒有控制權的情況下,您可以隨時在線程中運行代碼。 CPython有一個settrace函數用於在代碼中註冊跟蹤函數。爲了從使用類來測試這個想法,編寫了下面的代碼。問題是跟蹤似乎沒有發生,並且跟蹤日誌中沒有生成數據。什麼導致下面顯示的代碼中的問題?「sys.settrace」是否在Python 3.5中正常工作,但在Python 3.6中沒有正常工作?

#! /usr/bin/env python3 
import atexit 
import collections 
import pprint 
import sys 


def main(): 
    i = create_instance() 
    print(len(i.data), flush=True) 


def create_instance(): 
    instance = Tracer() 
    return instance 


class Tracer: 

    def __init__(self): 
     self.data = [] 
     sys.settrace(self.trace) 
     atexit.register(pprint.pprint, self.data) 
     atexit.register(sys.settrace, None) 

    def trace(self, frame, event, arg): 
     print('Tracing ...', flush=True) 
     self.data.append(TraceRecord(frame, event, arg)) 
     return self.trace 


TraceRecord = collections.namedtuple('TraceRecord', 'frame, event, arg') 


if __name__ == '__main__': 
    main() 

附錄:

問題在Windows上運行的Python 3.5的時候是看不出來的。但是,Python 3.6中不會出現跟蹤,因此跟蹤日誌不會被打印。如果有人能夠確認我的錯誤是一個很好的答案,那麼很可能提交的文件將被接受並授予賞金。

+0

您的代碼工作正常我(CPython 3.6.1)...然而,在*'main'內沒有*被追蹤 - 顯然'len' /'print'沒有被覆蓋。嘗試在'main'中添加對手動定義函數的調用。 – Zulan

回答

1

我試過你的程序,並且確實發佈了它沒有任何要跟蹤的內容。內置函數print()len()不會生成跟蹤事件,可能是因爲它們是由平臺定義的,並且假定它們的內部工作正常並且不感興趣。

的文檔狀態:

跟蹤功能調用(與事件設置爲「呼叫」),每當進入一個新的本地範圍;

我修改了你的程序來定義一個函數並調用它。當我這樣做,那麼你的跟蹤功能被調用。

功能我定義:

def doSomething(): 
    print("Hello World") 

我你main()功能的版本:

def main(): 
    i = create_instance() 
    print(len(i.data)) 
    doSomething() 
    print(len(i.data)) 

輸出我看到:

0 
Tracing ... 
Tracing ... 
Hello World 
Tracing ... 
3 
+0

該問題的代碼已被擴展爲更健壯一些,並有助於顯示其信息。你可以檢查Windows上的Python 3.5和Python 3.6的輸出是否不同嗎? –

相關問題