2012-05-27 68 views
2

時,代碼對象在導入期間有意外的文件名我正在嘗試編寫一個程序,該程序將跟蹤Python代碼並打印對局部變量值的更改報告。我使用簡單的賦值,循環和函數調用可以很好地工作,但是當我使用import語句時遇到問題。當使用sys.settrace()

我只想跟蹤主模塊中的代碼,我想在調用導入的模塊後立即停止跟蹤。當我導入一個我寫的簡單模塊時,我可以做到這一點,並且當幀的代碼對象指向不同的文件時,我就停止跟蹤。

但是,當我嘗試導入decimal模塊時,這不起作用。我可以消除decimal模塊中運行的大部分代碼,但我有一個叫做DecimalTuple的代碼塊,它聲稱在主模塊中運行。然而,這沒有任何意義,因爲行號不存在於該模塊中。

框架或代碼對象上是否還有一些其他屬性可以用來說明DecimalTuple不在主模塊中?很明顯,我可以爲DecimalTuple添加一個特殊情況,但如果其他模塊有同樣的問題,那不會對我有幫助。

這是我的例子。它執行引用的代碼並用settrace()跟蹤呼叫。如果您註釋掉global_trace()的前兩行,它還會顯示在其他模塊中執行的所有代碼。

import sys 

class tracer: 

    count = 0 

    def __init__(self): 
     self.index = tracer.count = tracer.count + 1 

    def global_trace(self, frame, event, arg): 
     if frame.f_code.co_filename != '<string>': 
      return 
     print 'global %d, line %d: %s, %s' % (self.index, 
             frame.f_lineno, 
             event, 
             frame.f_code) 
     return tracer().local_trace 

    def local_trace(self, frame, event, arg): 
     print 'local %d, line %d: %s, %s' % (self.index, 
             frame.f_lineno, 
             event, 
             frame.f_code) 
     return self.local_trace 

code = """\ 
def foo(r): 
    return r + 3 

y = foo(2) 

import decimal 

x = decimal.Decimal('10') 
""" 

sys.settrace(tracer().global_trace) 

exec code in dict() 

這裏是跟蹤輸出。您可以看到foo()的調用及其執行全部位於<string>模塊中,該模塊表示我作爲主模塊傳入的代碼字符串。但是,當它到達第6行的導入語句時,它會開始調用不可能位於<string>模塊中的代碼。

global 1, line 1: call, <code object <module> at 0x266a030, file "<string>", line 1> 
local 2, line 1: line, <code object <module> at 0x266a030, file "<string>", line 1> 
local 2, line 4: line, <code object <module> at 0x266a030, file "<string>", line 1> 
global 1, line 1: call, <code object foo at 0x266a730, file "<string>", line 1> 
local 3, line 2: line, <code object foo at 0x266a730, file "<string>", line 1> 
local 3, line 2: return, <code object foo at 0x266a730, file "<string>", line 1> 
local 2, line 6: line, <code object <module> at 0x266a030, file "<string>", line 1> 
global 1, line 1: call, <code object <module> at 0x27c2130, file "<string>", line 1> 
local 4, line 1: line, <code object <module> at 0x27c2130, file "<string>", line 1> 
global 1, line 1: call, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1> 
local 5, line 1: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1> 
local 5, line 2: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1> 
local 5, line 4: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1> 
local 5, line 6: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1> 
local 5, line 8: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1> 
local 5, line 12: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1> 
local 5, line 13: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1> 
local 5, line 20: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1> 
local 5, line 24: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1> 
local 5, line 28: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1> 
local 5, line 30: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1> 
local 5, line 37: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1> 
local 5, line 41: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1> 
local 5, line 42: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1> 
local 5, line 43: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1> 
local 5, line 43: return, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1> 
local 4, line 1: return, <code object <module> at 0x27c2130, file "<string>", line 1> 
local 2, line 8: line, <code object <module> at 0x266a030, file "<string>", line 1> 
local 2, line 8: return, <code object <module> at 0x266a030, file "<string>", line 1> 

回答

2

出現這種情況,因爲事實證明,因爲collections.namedtuple做一些非常hinky的事情(和DecimalTuplenamedtuple,所以你要import decimal調用隨後調用的代碼)。當它發生時,周圍線300 collections.py(在Python 2.7,至少 - 你的行號可能在不同的版本有所不同),你會看到一個評論,說:

# Execute the template string in a temporary namespace and 
# support tracing utilities by setting a value for frame.f_globals['__name__'] 

在此之後的代碼會導致您的示蹤劑曲解它在觀察什麼 - 因爲創建該類的模板是使用exec本身完成的,所以在<string>「文件」中執行的代碼更多,而不是<string>

+0

完美的作品,謝謝。我愛堆棧溢出! –