Get a list of the names of all functions in a Python module in the order they appear in the file?

Question:

The globals function returns a dictionary that contains the functions in a module, and the dir function returns a list that contains the names of the functions in a module, but they are in alphabetical order or are in a dictionary.

Is there a way to get the names of all the functions in a module in the order they appear in a file?

Asked By: davidscolgan

||

Answers:

Here is my solution. Read in the source file as a string, filter out lines that begin with def, strip leading whitespace and extract the substring between the first space and first left paren.

def extract_fns(filename):
    with open(filename) as f:
        lines = f.readlines()
        return [line.split(' ', 1)[1].split('(')[0] for line in lines
            if line.strip().startswith('def')]
Answered By: davidscolgan

When I had a need like this, I used a decorator.

def remember_order(func, counter=[0]):
    func._order = counter[0]
    counter[0] += 1
    return func

@remember_order
def foo():
    print "foo"

@remember_order
def bar():
    print "bar"

@remember_order
def baz():
    print "baz"

Yes, you have to decorate each function individually. Explicit is better than implicit, as they say, and because you are doing something unnatural it’s good to call it out as plainly as possible.

Now you want to get all the decorated functions in the order they were defined?

import sys
module = sys.modules[__name__]   # get reference to current module
# you could also use a reference to some other module where the functions are

# get the functions in the order defined
funcs = sorted((func for func in
              (getattr(module, name) for name in dir(module))
              if callable(func) and hasattr(func, "_order")),
              key = lambda func: func._order)

# call them in that order
for func in funcs:
    func()

But it’d be easier to just give them names in alphabetical order…

Answered By: kindall

My solution was to parse the ast. As it turns out elements in the ast tree are in the order they are parsed. Hence functions are in the order they appear in the file.

import inspect
import ast

def get_function_names_in_order_of_appearence(module_name):

    this_source = inspect.getsource(module_name)
    tree = ast.parse(this_source)
    functions = []

    for elem in tree.body:
        if type(elem) is ast.FunctionDef:
            this_func_name = elem.name
            functions.append(this_func_name)
            
    return functions

Assuming the module that is to be analyzed is:

# fancy_module
def z_func(x):
    return x+1
def a_func(a, b): 
    pass
def b_func(mystr, **kw):
    pass

Will give:

func_list = get_function_names_in_order_of_appearence(fancy_module)

for func in func_list:
    print(func)

# -------
# output:
z_func
a_func
b_func

The advantage is you can add other stuff from the ast tree, like the signatures of the functions.

Answered By: Thomas Anderson
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.