Getattr на пакет в Python

В Python есть ли эквивалент getattr() на модуле для пакетов? Другими словами, есть ли способ найти функцию в пакете, подобную приведенной ниже?

Intents/
|-- __init__.py
|-- foo.py
|-- bar.py
|-- baz.py

2 ответа

Решение

Ты можешь использовать getattr получить любой объект из модуля Python:

In [4]: cat bla.py

def foo():
    pass

In [5]: import bla


In [6]: getattr( bla, 'foo')
Out[6]: <function bla.foo>

Таким образом, вы можете пройти все модули в пакете, и try... except с getattr чтобы найти, какой модуль содержит нужный класс или функцию (вы также можете импортировать любой другой объект верхнего уровня)

Вы действительно не сказали точно, что вы хотели вернуть, если функция найдена, поэтому следующее просто возвращает имя модуля.

Если вы добавили следующее определение функции к вашему __init__.py файл:

def find_func(func_name):
    """ Return name of package module that contains named function. """
    import os
    import sys
    import traceback
    import types

    # dynamically imports all the python modules in sub directory
    package_path = os.path.split(__file__)[0]
    package_directory = os.path.split(package_path)[1]

    for fn in os.listdir(package_directory):
        globals_, locals_ = globals(), locals()
        # process all python files in directory that don't start with underscore
        if fn[0] != '_' and fn.split('.')[-1] in ('py', 'pyw'):
            modulename = fn.split('.')[0]  # filename without extension
            subpackage = ".".join([package_directory, modulename])
            try:
                module = __import__(subpackage, globals_, locals_, [modulename])
            except:
                traceback.print_exc(file=sys.stdout)
                raise  # reraise exception
            # see if this module has the named function
            obj = getattr(module, func_name, None)
            if isinstance(obj, (types.FunctionType, types.LambdaType)):
                return modulename

    return None  # not found

Затем вы можете сделать следующее в пакетных клиентах:

import Intents

print(Intents.find_func('func_in_bar'))  # --> bar
Другие вопросы по тегам