0

I have a folder containing various Python files, each including some functions called tasks. I want to do two things:

Instead of writing

from module.file1 import function1, function2
from module.file2 import function3

I would prefer to do:

from module import function1, function2, function3

In addition to that, I need a list of all functions names (as str) which available in this directory (excluding built-ins).

So far I tried writing a __init__.py with the following content:

from os.path import dirname, basename, isfile, join
import glob
modules = glob.glob(join(dirname(__file__), "*.py"))

functions = []

for m in modules:
    if isfile(m) and not m.endswith('__init__.py'):
        functions = [getattr(m, f) for f in dir(m) if callable(getattr(m, f))]

print(functions)

However, functions now contains all built-in functions but not the one was was looking for. In addition, how do I "return" the functions for import and how can I get the list of function names (string only) for further use?

5
  • m is a string, not a module. Commented Nov 15, 2020 at 12:14
  • Thanks for the comment. Changing it to getattr(m, f) somehow helps, now functions contains a lot of stuff. It does include all builtin functions though and not the function I was hoping for. Commented Nov 15, 2020 at 12:28
  • What you get are actually the methods of str. Commented Nov 15, 2020 at 12:29
  • Why? dir(m) should list the attributes of the modules identified by the path, right? Commented Nov 15, 2020 at 12:31
  • docs.python.org/3/library/functions.html#dir Commented Nov 15, 2020 at 12:54

2 Answers 2

1

I found a way how to solve it.

__init__.py looks as follows

__all__ = []

import pkgutil
import inspect

for loader, name, is_pkg in pkgutil.walk_packages(__path__):
    module = loader.find_module(name).load_module(name)

    for fname, value in inspect.getmembers(module, inspect.isfunction):
        if fname.startswith('__'):
            continue

        if value.__module__ != module.__name__:
            continue

        globals()[fname] = value
        __all__.append(fname)

It does the additional check for the module name to make sure I don't list imported functions but only those defined in the module. In the other file I then include it with:

from tasks import __all__ as function_names
import tasks

functions = [getattr(tasks, f) for f in function_names]
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much! I've been looking for a way to do this, but keep running into answers for importing modules and not functions.
0

The condition you use to filter is incorrect, try the following -

functions = [getattr(m, f) for f in dir(m) if callable(getattr(m, f))]

p.s consider using inspect module

3 Comments

As already noted under the question, m is a string, so what do you expect dir(m) to return?
Thanks for the answer. Changing it to getattr(m, f) somehow helps, now functions contains a lot of stuff. It does include all builtin functions though and not the function I was hoping for. It also does not explain the main part of the question how to "return" the functions so that the imports work and how to get a string list of functions.
See @ThierryLathuille comment, you should probably make sure you use the modules and not the strings.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.