0
我已經開始編寫一個小型的Python實用程序來緩存函數。可用的緩存工具(lru_cache
,Beaker)未檢測到子功能的更改。pycallgraph的非圖形輸出
爲此,我需要一個調用圖。 pycallgraph由Gerald Kaszuba存在一個很好的工具。不過,到目前爲止,我只知道它輸出函數名字符串。我需要的是函數對象或函數代碼散列。
我指的是這兩個詞是什麼:讓def foo(x): return x
,然後foo
是功能對象,hash(foo.__code__.co_code)
是功能代碼的哈希。
我有什麼
你可以看到我有什麼here。但下面是一個簡單的例子。我在這個例子中遇到的問題是,我無法再從函數名(字符串)到函數定義。我正在嘗試eval(func)
。
所以,我想有解決這個的方法有兩種:
- 正確
pycallgraph.output
,或者一些otherway得到我直接從Pycallgraph希望。 - 動態加載
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()