Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

get the lists of functions used/called within a function in python

Is there any tool/library through which the list of methods/functions called within another methods/functions can be listed?

For example: If that tool or library runs for below method

def calculate(a: int, b: int, operator: Operator):
    if operator == Operator.add:
        add(a, b)
    elif operator == Operator.subtract
        subtract(a, b)

then it should return

1. add
2. subtract

This question is almost same as this one but it's for Java.

This is basically same as what PyCharm does for Find Usage. Thanks!

like image 898
Pallav Jha Avatar asked Aug 17 '18 19:08

Pallav Jha


People also ask

How do you pull a list from a function in Python?

A Python function can return any object such as a list. To return a list, first create the list object within the function body, assign it to a variable your_list , and return it to the caller of the function using the keyword operation “ return your_list “.

How do you get a function name inside a function in Python?

Method 1: Get Function Name in Python using function. func_name.

How do you list all functions in Python?

We can list down all the functions present in a Python module by simply using the dir() method in the Python shell or in the command prompt shell.

Can you define a function within a function Python?

If you define a function inside another function, then you're creating an inner function, also known as a nested function. In Python, inner functions have direct access to the variables and names that you define in the enclosing function.


1 Answers

This seems to do the work:

import dis
def list_func_calls(fn):
    funcs = []
    bytecode = dis.Bytecode(fn)
    instrs = list(reversed([instr for instr in bytecode]))
    for (ix, instr) in enumerate(instrs):
        if instr.opname=="CALL_FUNCTION":
            load_func_instr = instrs[ix + instr.arg + 1]
            funcs.append(load_func_instr.argval)

    return ["%d. %s" % (ix, funcname) for (ix, funcname) in enumerate(reversed(funcs), 1)]

Example:

>>> list_func_calls(calculate)
['1. add', '2. subtract']

What's happening here is:

  1. we make a Bytecode object of the function
  2. we reverse the list of instructions, since the function name will follow the function call
  3. we step through the list, and for each CALL_FUNCTION instruction,

  4. we use the instructions arg parameter to tell us how many arguments we're getting

  5. we look one past that to find the instruction that loads the function we're calling

  6. we add that function's name (instr.argval) to a list which we then reverse, enumerate, and return in the requested format

Note that since Python 3.6, there are three CALL_FUNCTION instructions, so you'll have to check the documentation to extend this example to be fully functional with current python

like image 101
Jon Kiparsky Avatar answered Oct 25 '22 02:10

Jon Kiparsky