-1

i want to list all the functions in one module but i'm stuck on an point. i just get only the functions in __init__.py but not all the functions in the package. this is the code what i al ready have made:

import package
functions = []
for i in dir(package):
    functions.append(i)
print(functions)

so now i get a list of all functions in __init__.py but not over the whole package. how to get all the functions in 'package'? i want to get it like this:

import package
functions = []
for i in dir(package):
    #here like adding function and then make package function.other_package
print(functions)

can someone help me plz?

it is not a duplicate becuse i not want a doc but just only all the functions of all the files in a package

Matthijs990
  • 637
  • 3
  • 26

1 Answers1

2

The definition of what a package exactly is is a little tricky, so I'll only assume the very basics: You have a directory that you assume to be the package root, and a number of python files directly in it or nested deeper that you assume to be part of the package. Something like this maybe:

# package foo
foo
├── bar.py               # has a function "bar"
├── __init__.py          # has a function "foo" 
└── baz
    ├── qux.py           # has functions "baz" and "qux"
    └── __init__.py

And you expect something like this as the result:

foo/bar.py: [bar]
foo/__init__.py: [foo]
foo/baz/qux.py: [qux, baz]
foo/baz/__init__.py: []

If no other assumption is made, the only way to learn what functions your package contains is to ask python itself to compile the files and show their content:

import os
import inspect
import typing

# find all python files below a certain folder
files = []
for (dirpath, dirnames, filenames) in os.walk('path/to/a/package/foo'):
    for filename in filenames:
        if filename.endswith('.py'):
            files.append(os.sep.join([dirpath, filename]))

for f in files:
    # turn the files into code objects and find declared constants
    functions = []
    code_obj = compile(open(f).read(), f, 'exec')
    members = dict(inspect.getmembers(code_obj))
    for idx in range(len(members['co_consts'])//2):
        val = members['co_consts'][idx * 2]
        name = members['co_consts'][idx * 2 + 1]
        # suboptimal: this check also allows lambdas and classes 
        if isinstance(val, types.CodeType):
            functions.append(name)
    print(f'{f}: {functions}')

This snipped prints exactly the above result for me. As far as I know, there is no way to ask a package about all its functions, and not only those it willingly exposes.


See also this QA and this post for alternative and more accurate (albeit more complicated) ways to extract functions from code objects.

Arne
  • 17,706
  • 5
  • 83
  • 99