Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python:动态加载一次性插件?_Python_Dynamic_Plugins - Fatal编程技术网

python:动态加载一次性插件?

python:动态加载一次性插件?,python,dynamic,plugins,Python,Dynamic,Plugins,我正在编写一个python应用程序,希望在其中使用动态的、一次性可运行的插件 我的意思是,在这个应用程序运行的不同时间,它会在特定位置查找具有特殊名称的python源文件。如果找到任何这样的源文件,我希望我的应用程序加载它,在其中运行一个预先命名的函数(如果存在这样的函数),然后忘记该源文件 稍后在应用程序运行期间,该文件可能已经更改,我希望我的python应用程序重新加载它,执行它的方法,然后像以前一样忘记它 标准导入系统在初始加载后保持模块驻留,这意味着后续的“导入”或“\uuuuu导入\u

我正在编写一个python应用程序,希望在其中使用动态的、一次性可运行的插件

我的意思是,在这个应用程序运行的不同时间,它会在特定位置查找具有特殊名称的python源文件。如果找到任何这样的源文件,我希望我的应用程序加载它,在其中运行一个预先命名的函数(如果存在这样的函数),然后忘记该源文件

稍后在应用程序运行期间,该文件可能已经更改,我希望我的python应用程序重新加载它,执行它的方法,然后像以前一样忘记它

标准导入系统在初始加载后保持模块驻留,这意味着后续的“导入”或“\uuuuu导入\uuuuuu”调用不会在初始导入后重新加载相同的模块。因此,在第二次到第n次导入期间,将忽略此源文件中对python代码的任何更改

为了使这样的包每次都被唯一地加载,我提出了以下过程。它是有效的,但对我来说似乎有点“黑客”。有没有更优雅或更喜欢的方法?(请注意,以下是一个过度简化的示例)

附录:其中一个问题是func()在单独的模块上下文中运行,并且它无法访问调用方空间中的任何函数或变量。因此,我必须做不雅观的事情,如以下,如果我 希望在调用中可以访问func_one()、func_two()和abc 函数()的类型:


非常感谢。

您使用的方法非常好。对于这个问题

这样做的一个问题是func()在单独的模块上下文中运行,并且它无法访问调用方空间中的任何函数或变量

最好使用
execfile
函数:

# main.py
def func1():
  print ('func1 called')
exec(open('trackableClass.py','r').read(),globals()) # this is similar to import except everything is done in the current module
#execfile('/path/to/plugin.py',globals())  # python 2 version
func()
测试它:

#/path/to/plugin.py
def func():
  func1()
结果:

python main.py
# func1 called

这种方法的一个潜在问题是名称空间污染,因为每个文件都在当前名称空间中运行,这会增加名称冲突的可能性。

您使用的方法完全可以。对于这个问题

这样做的一个问题是func()在单独的模块上下文中运行,并且它无法访问调用方空间中的任何函数或变量

最好使用
execfile
函数:

# main.py
def func1():
  print ('func1 called')
exec(open('trackableClass.py','r').read(),globals()) # this is similar to import except everything is done in the current module
#execfile('/path/to/plugin.py',globals())  # python 2 version
func()
测试它:

#/path/to/plugin.py
def func():
  func1()
结果:

python main.py
# func1 called

这种方法的一个潜在问题是名称空间污染,因为每个文件都在当前名称空间中运行,这增加了名称冲突的可能性。

我使用以下代码来完成这类工作

请注意,我实际上并没有将代码作为模块导入,而是在特定上下文中执行代码。这让我可以定义一组插件自动可用的api函数,用户无需导入任何内容

def load_plugin(filename, context):
    source = open(filename).read()
    code = compile(source, filename, 'exec')
    exec(code, context)
    return context['func']

context = { 'func_one': func_one, 'func_two': func_two, 'abc': abc }
func = load_plugin(filename, context)
func()

这个方法在Python2.6+和Python3.3+中都可以使用。

我使用下面的代码来做这类事情

请注意,我实际上并没有将代码作为模块导入,而是在特定上下文中执行代码。这让我可以定义一组插件自动可用的api函数,用户无需导入任何内容

def load_plugin(filename, context):
    source = open(filename).read()
    code = compile(source, filename, 'exec')
    exec(code, context)
    return context['func']

context = { 'func_one': func_one, 'func_two': func_two, 'abc': abc }
func = load_plugin(filename, context)
func()

这个方法在Python2.6+和Python3.3+中都可以使用

虽然有点粗糙,但我看不出你的方法有任何错误。但是,就代码而言,您永远不应该捕获所有异常,除了:。相反,捕获特定的异常,例如
除了keyrerror:
除了IOError:
。谢谢。正如我所说,我的代码过于简单。在现实世界中,我的错误检查要广泛得多。还有,请阅读我的附录,这是我在您写评论后添加的。为什么不使用
reload(module)
builtin函数呢?啊哈!重新加载(模块)是我一直在寻找的。然而,它仍然没有解决我在补遗中提出的问题。也许我不得不忍受这些限制,但是???理想情况下,我希望动态地将我的动态python函数加载到_current_名称空间中。但是,就代码而言,您永远不应该捕获所有异常,除了:。相反,捕获特定的异常,例如
除了keyrerror:
除了IOError:
。谢谢。正如我所说,我的代码过于简单。在现实世界中,我的错误检查要广泛得多。还有,请阅读我的附录,这是我在您写评论后添加的。为什么不使用
reload(module)
builtin函数呢?啊哈!重新加载(模块)是我一直在寻找的。然而,它仍然没有解决我在补遗中提出的问题。也许我不得不忍受这些限制,但是???理想情况下,我希望动态地将我的动态python函数加载到_current_名称空间中。我以前在execfile()方面遇到过问题,这就是我提出的方法的原因。但也许这些都是我的编码问题。我会做一些测试,然后很快回来解释我的execfile()问题,或者声明问题已经解决。execfile在3.x中不可用;我需要加载文件,编译然后执行。也许六号有一个兼容功能。。。。是的,我现在重新发现了我遇到的execfile()问题。execfile()的第2次到第n次调用不会覆盖初始execfile调用()的加载。换句话说,如果文件是通过execfile()加载的,func()最初返回1,然后如果我更改文件使func()返回2,则后续的execfile()调用仍然会导致func()返回1。这非常令人惊讶,因为我用winPython2.7.10在我的机器上测试它,并且没有这样的问题,所以你可以在Python3中找到一个与execfile等效的方法:我以前在execfile()上遇到过问题,这就是我提出的方法的原因。但也许那些是密码子