0

我的电脑上有一个打开的文件夹,

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. 上面__init__的代码不起作用,因为调用时 sys.modules[__name__]is而不是我想要的or ,有没有办法避免将 the 传递给on the or the ?____inspectOpenFunctionsmodule_aasys.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中标记的问题

    [http://stackoverflow.com/questions/5027352/how-to-test-if-one-python-module-has-been-imported]

  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

4

1 回答 1

2

首先解决您的最后一个问题:要在最新版本的 Python 中动态导入模块,请使用importlib.import_module(),这就是它的用途。如果您使用的是较旧版本的 Python,则应该__import__改用(但请检查文档中该直接方法的特质 -import_module()添加该函数作为替代品是有原因的)。

为了解决您的第一个问题:没有官方可移植的方法来检索有关调用函数的全局环境的信息,因此最正确的答案是__name__在需要的地方简单地作为参数传入。

在 Python 中重新加载总是有点危险,因为在重新加载时并非一切都正常工作(如果重新加载它们或它们引用的模块,即使许多标准库模块也会失败)。

我真的建议花一些时间来探索这个关于 Python 中插件架构的现有问题的答案:Building a minimum plugin architecture in Python

于 2011-02-18T06:53:40.353 回答