我正在写一个python应用程序,我想在其中使用动态的,一次运行的插件。python:动态加载一次性插件?
我的意思是,在这个应用程序的运行过程中不同的时间,它看起来与在特定地区的特殊名称的Python源文件。如果找到任何这样的源文件,我希望我的应用程序加载它,在其中运行一个预先命名的函数(如果存在这样的函数),然后忘记该源文件。应用程序的运行过程中后来
,该文件可能已经改变了,我想我的Python应用程序重新加载它,执行它的方法,然后忘掉它,像以前一样。
标准导入系统保持模块居民初始加载后,这意味着随后的“进口”或“__import__”调用不会加载其初始导入后,在同一个模块。因此,在源文件中对Python代码所做的任何更改在第二次到第n次导入时都将被忽略。
为了使这种封装唯一每次被加载,我想出了下面的过程。它的工作原理,但对我来说似乎有些“哈克”。有没有更优雅或更喜欢的方式来做到这一点? (请注意,下面是一个简化的过度,说明性示例)
import sys
import imp
# The following module name can be anything, as long as it doesn't
# change throughout the life of the application ...
modname = '__whatever__'
def myimport(path):
'''Dynamically load python code from "path"'''
# get rid of previous instance, if it exists
try:
del sys.modules[modname]
except:
pass
# load the module
try:
return imp.load_source(modname, path)
except Exception, e:
print 'exception: {}'.format(e)
return None
mymod = myimport('/path/to/plugin.py')
if mymod is not None:
# call the plugin function:
try:
mymod.func()
except:
print 'func() not defined in plugin: {}'.format(path)
附录:一个问题这是FUNC()一个单独的模块上下文中运行,并且它具有内的任何函数或变量没有访问来电者的空间。因此,我必须做类似下面的东西不雅如果我想 func_one(),func_two()和ABC的调用FUNC的 ()内为可访问:
def func_one():
# whatever
def func_two():
# whatever
abc = '123'
# Load the module as shown above, but before invoking mymod.func(),
# the following has to be done ...
mymod.func_one = func_one
mymod.func_two = func_two
mymod.abc = abc
# This is a PITA, and I'm hoping there's a better way to do all of
# this.
非常感谢你。
虽然有点哈克,我看不出有什么毛病你的方法。不过,就你的代码而言,你绝不应该用'except:'来捕获所有异常。相反,要捕获特定的异常,例如'除了KeyError:'或'除了IOError:'外。 –
谢谢。正如我所说的,我的代码过于简单化了。在现实世界中,我的错误检查更为广泛。但是,请阅读我的附录,在您发表评论之后,我添加了该附录。 – HippoMan
为什么不使用'reload(module)'内建函数? https://docs.python.org/2/library/functions.html#reload – gdlmx