2014-12-05 67 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中的新字段。