È possibile estrarre tutte le espressioni di chiamata con:
import ast
class CallCollector(ast.NodeVisitor):
def __init__(self):
self.calls = []
self.current = None
def visit_Call(self, node):
# new call, trace the function expression
self.current = ''
self.visit(node.func)
self.calls.append(self.current)
self.current = None
def generic_visit(self, node):
if self.current is not None:
print "warning: {} node in function expression not supported".format(
node.__class__.__name__)
super(CallCollector, self).generic_visit(node)
# record the func expression
def visit_Name(self, node):
if self.current is None:
return
self.current += node.id
def visit_Attribute(self, node):
if self.current is None:
self.generic_visit(node)
self.visit(node.value)
self.current += '.' + node.attr
Utilizzare questo con un albero ast
parse:
tree = ast.parse(yoursource)
cc = CallCollector()
cc.visit(tree)
print cc.calls
Demo:
>>> tree = ast.parse('''\
... def foo():
... print np.random.rand(4) + np.random.randn(4)
... print linalg.norm(np.random.rand(4))
... ''')
>>> cc = CallCollector()
>>> cc.visit(tree)
>>> cc.calls
['np.random.rand', 'np.random.randn', 'linalg.norm']
È possibile che questo deambulatore gestisce solo i nomi e attributi; se hai bisogno di un supporto per le espressioni più complesso, dovrai estenderlo.
Si noti che la raccolta di nomi come questo è non è un compito banale. Qualsiasi riferimento indiretto non verrebbe gestito. È possibile creare un dizionario nel proprio codice di funzioni per chiamare e scambiare dinamicamente gli oggetti funzione, e l'analisi statica come quella precedente non sarà in grado di seguirla.
fonte
2014-09-24 11:03:57
Questo non è così facile come si pensa che potrebbe essere. Che dire di callables memorizzati come riferimenti in qualcos'altro? Supponiamo che tu abbia un dizionario con '{'foo': np.random.rand, 'bar': linalg.norm}' quindi usa quelle chiamabili tramite i tasti nel dizionario. Prendi in considerazione che il tuo codice può quindi riassociare anche quelle chiavi, scambiando dinamicamente i nomi .. –
In altre parole, la risoluzione dei nomi completi completi non è necessariamente semplice né tagliente e secca. –
Detto questo, è possibile catturare tutti i nodi 'ast.Call' ed estrarre l'espressione' func' (sarà un albero più piccolo di nodi 'ast', compresi' ast.Name' e 'ast.Attribute'). –