我正在寫一個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