我正在编写一个python应用程序,允许用户编写自己的插件并扩展我提供的核心功能 -
$ tree project_dir/
.
├── application.py
├── plugins
│ ├── __init__.py
│ ├── example_plugin.py
│ ├── plugin1.py
│ ├── plugin2.py
│ └── plugin3
│ ├── sounds
│ │ └── test.wav
│ └── player.py
└── plugins_manager.py
plugins_manager.py -
class Manager(object):
def __init__(self):
self.plugins = {}
def register_plugin(self, name, plugin_func):
self.plugins[name] = plugin_func
application.py全局初始化Manager
实例 -
manager = Manager()
def main():
print manager.plugins
main()
每个插件都需要从Manager
导入application.py
实例并注册自己,如plugin1.py -
from application import manager
PLUGIN_NAME = "AAC_Player"
def plugin_function(options):
# do something
manager.register_plugin(PLUGIN_NAME, plugin_function)
现在,当我运行application.py时,显然没有任何内容被打印出来。如何在程序启动时自己注册插件(调用.register_plugin()
)?
所以在这一行上,一个更普遍的问题是 - 如何让python执行一行代码,这些代码在文件中是全局的而不实际运行文件?
欢迎改进插件架构的建议!
答案 0 :(得分:2)
您可以使用__import__()
内置来导入插件,然后在插件文件register_plugin()
或example_plugin.py
中包含__init__.py
调用(如果它是目录)。
例如,假设这是您的项目结构:
./
application.py
plugins_manager.py
plugins/
__init__.py
plugin1.py
plugin2.py
plugin3/
__init__.py
插件包含以下内容:
$ cat plugins/plugin1.py
print 'Plugin 1'
$ cat plugins/plugin2.py
print 'Plugin 2'
$ cat plugins/plugin3/__init__.py
print 'Plugin 3'
在plugins_manager.py
中,识别插件并将其导入:
from os import listdir
from os.path import exists, isdir, basename, join, splitext
def is_plugin(filename):
filepath = join('plugins', filename)
_, ext = splitext(filepath)
# Ignore plugins/__init__.py
if filename == '__init__.py':
return False
# Find single file plugins
if ext == '.py':
return True
# Find plugins packaged in directories
if isdir(filepath) and exists(join(filepath, '__init__.py')):
return True
return False
plugin_names = [ splitext(p)[0] for p in listdir('plugins/') if is_plugin(p) ]
plugins = [ __import__('plugins.' + p) for p in plugin_names ]
输出应该类似于:
Plugin 1
Plugin 2
Plugin 3
请注意,在这种情况下,plugins
变量包含导入的模块对象的列表。
答案 1 :(得分:0)
严格地说,如果没有以某种方式调用代码,我就无法运行代码。为此,正在运行的程序可以使用
import importlib
这样,一旦找到该文件,您就可以将其导入:
mod = importlib.import_module(import_name, pkg_name)
如果该文件提供已知函数(在本例中为Run),则可以使用:
调用它mod.Run(your_args)
这适用于Python 2.7。版本3可能不同。