2014-12-05 105 views
0

我已經開始編寫一個小型的Python實用程序來緩存函數。可用的緩存工具(lru_cacheBeaker)未檢測到子功能的更改。pycallgraph的非圖形輸出

爲此,我需要一個調用圖pycallgraphGerald Kaszuba存在一個很好的工具。不過,到目前爲止,我只知道它輸出函數名字符串。我需要的是函數對象函數代碼散列。

我指的是這兩個詞是什麼:讓def foo(x): return x,然後foo是功能對象,hash(foo.__code__.co_code)功能代碼的哈希

我有什麼

你可以看到我有什麼here。但下面是一個簡單的例子。我在這個例子中遇到的問題是,我無法再從函數名(字符串)到函數定義。我正在嘗試eval(func)

所以,我想有解決這個的方法有兩種:

  1. 正確pycallgraph.output,或者一些otherway得到我直接從Pycallgraph希望。
  2. 動態加載function.__name__字符串中的函數。

import unittest 
from pycallgraph import PyCallGraph 
from pycallgraph.output import GraphvizOutput 

class Callgraph: 
    def __init__(self, output_file='callgraph.png'): 
     self.graphviz = GraphvizOutput() 
     self.graphviz.output_file = output_file 

    def execute(self, function, *args, **kwargs): 
     with PyCallGraph(output=self.graphviz): 
      ret = function(*args, **kwargs) 

     self.graph = dict() 
     for node in self.graphviz.processor.nodes(): 
      if node.name != '__main__': 
       f = eval(node.name) 
       self.graph[node.name] = hash(f.__code__.co_code) 
     return ret 

    def unchanged(self): 
     '''Checks each function in the callgraph whether it has changed. 
     Returns True if all the function have their original code-hash. False otherwise. 
     ''' 
     for func, codehash in self.graph.iteritems(): 
      f = eval(func) 
      if hash(f.__code__.co_code) != codehash: 
       return False 
     return True 

def func_inner(x): 
    return x 
def func_outer(x): 
    return 2*func_inner(x) 

class CallgraphTest(unittest.TestCase): 
    def testChanges(self): 
     cg = Callgraph() 
     y = cg.execute(func_outer, 3) 
     self.assertEqual(6, y) 
     self.assertTrue(cg.unchanged()) 
     # Change one of the functions 
     def func_inner(x): 
      return 3+x 
     self.assertFalse(cg.unchanged()) 
     # Change back! 
     def func_inner(x): 
      return x 
     self.assertTrue(cg.unchanged()) 


if __name__ == '__main__': 
    unittest.main() 

回答

0

我已經修補tracer.py與適當的哈希解決了這個。

  # Work out the current function or method 
     func_name = code.co_name 
+  func_hash = hash(code.co_code) 

我計算只是其中的函數名的保存價值。稍後,您顯然還需要保存該值。我正在用func_name是關鍵字和散列值的字典來做這件事。在創建節點的函數中,我將其分配給stat_group中的新字段。