автоматический импорт всех подмодулей в папке, затем вызовет функции с одинаковыми именами - Python runtime inspect related - PullRequest
0 голосов
/ 18 февраля 2011

У меня есть открытая папка на моем компьютере,

OpenFunctions\
    ____Template.py
    function1.py
    function2.py
    ......
    functionx.py

Эта папка является экспериментальной целью для расширения возможностей всего приложения.Так что давайте просто подумаем, что это быстрая и сухая попытка, в данном случае не нужно учитывать соображения безопасности.

Моя цель - если я уроню functionx.py после ____Template.py, приложение может знать, что новые функциидоступны и будут вызывать функции, определенные в этом новом присоединенном файле, в некотором роде - что-то вроде системы плагинов, но должно быть немного по-другому.

Так что я написал ____inspect.py, может дать приложению возможность знать, чтобыл введен.

Вот

____inspect.py

def get_this_file_defined_functions(name_filter = "__"):
    import inspect, sys 
    f = inspect.getmembers(sys.modules[__name__], inspect.isfunction) 
    return [x for x in f if not x[0].startswith(name_filter)] 

def get_this_module_sub_modules(name_filter = "__"):
    import os.path, pkgutil
    pkgpath = os.path.dirname(__file__)
    m = [name for _, name, _ in pkgutil.iter_modules([pkgpath])] 
    return [x for x in m if not x[0].startswith(name_filter)]

def import_sub_modules_under_me(auto_exec_function = "auto_exec"):
    m = get_this_module_sub_modules()
    for i in m:  # need try except later
        exec "global %s; import %s" % (i, i)  
        #this will auto invoke __init__.py if sub modules folder is included
    for i in m:
        try:
            eval(i).eval(auto_exec_function)()
        except AttributeError:
            print "module %s has no function %s", % (i, auto_exec_function) 
        else:
            print "error on execute %s in module %s", % (auto_exec_function, i)

def execute_all_homonymy_functions(exec_function = "exec"):
    m = get_this_module_sub_modules()
    for i in m:
        #I need here for test if the module has been imported
        eval(i).eval(exec_function)()

Вот

____Template.py

def __you_can_not_see_me(): pass  # because filtered by str.startswith()
def auto_exec(): pass             # this will be auto executed
def you_can_get_me(): pass
def you_can_get_me1(): pass
def you_can_get_me2(): pass

, основанный на представленной выше идее. Я также хочу расширить структуру до уровня ниже

main.py
____inspect.py
OpenFunctions\
    __init__.py
    ____Template.py
    function1.py
    function2.py
    ......
    functionx.py
    module_aa
        \__init__.py
          aa.py
          aa1.py

Вот main.py, тогда как __init__.py может выглядеть как

import ____inspect
____inspect.import_sub_modules_under_me()
____inspect.execute_all_homonymy_functions("what_ever_i_want")

Вопросы:

  1. Выше *Код 1033 * не будет работать, потому что sys.modules[__name__] это ____inspect при вызове, но не OpenFunctions или module_aa Я хочу, есть ли способ избежать передачи sys.modules[__name__] в import_sub_modules_under_me() на main.py или __init__.py?

  2. Полагаю, execute_all_homonymy_functions() будет выполнять все те же функции именв папке, независимо от того, существует ли она в подмодуле или в одном файле, но я хочу вызвать все и последнюю версию в случае, если модуль был добавлен или источник был изменен во время выполнения.Тогда я хочу использовать код import aa, reload(aa), но можно подумать, что он неправильный по ссылке ниже, какие-либо предложения?Проблема, которую я отметил I need here for test if the module has been imported в _ _inspect.py

    [/5302326/kak-proverit-byl-li-importirovan-odin-modul-python]

  3. Я также хочу знать тип возврата одной функции в файле перед вызовомэто, было предложено прикрепить украшение на каждую функцию.Итак, мой план:

\ n

____decorate.py

def attrs(**kwds):
     def decorate(f):
         for k in kwds:
             setattr(f, k, kwds[k])
         return f
     return decorate

functionx.py
import ../____decorate.py

@attrs(argument_types=(int, int,),returns=int)
def __you_can_not_see_me(): pass

@attrs(argument_types=(int, int,),returns=int)
def auto_exec(): pass             # I will be auto executed

@attrs(argument_types=(int, int,),returns=int)
def you_can_get_me(): pass

@attrs(argument_types=(int, int,),returns=int)
def you_can_get_me1(): pass

@attrs(argument_types=(int, int,),returns=int)
def you_can_get_me2(): pass

Это нормально работает для проверки дела?Или есть лучшее решение?

Последнее: приведенный ниже код

exec "global %s; import %s" % (i, i) 
eval(i).eval(auto_exec_function)()

выглядит безобразно, есть ли альтернатива для двух строк выше?

Спасибо за вашу помощь.

Rgs,KC

1 Ответ

2 голосов
/ 18 февраля 2011

Чтобы ответить на последний вопрос: чтобы динамически импортировать модули в последних версиях Python, используйте importlib.import_module(), вот для чего он. Если вы используете более старую версию Python, вам следует вместо этого использовать __import__ (но проверьте особенности этого прямого подхода в документации - есть причина, по которой функция import_module() была добавлена ​​в качестве замены).

Чтобы ответить на ваш первый вопрос: не существует официально переносимого способа получения информации о глобальной среде вызывающей функции, поэтому самый правильный ответ - просто передать __name__ в качестве аргумента везде, где это необходимо.

Перезагрузка в Python всегда немного опасна, так как при перезагрузке не все работает правильно (даже многие стандартные библиотечные модули не будут работать, если вы перезагрузите либо их, либо модуль, на который они ссылаются).

Я действительно предлагаю потратить некоторое время на изучение ответов на этот существующий вопрос об архитектурах плагинов в Python: Создание минимальной архитектуры плагинов в Python

...