Python 如何在不调用文件的情况下运行全局代码
我正在编写一个python应用程序,它允许用户编写自己的插件并扩展我提供的核心功能-Python 如何在不调用文件的情况下运行全局代码,python,Python,我正在编写一个python应用程序,它允许用户编写自己的插件并扩展我提供的核心功能- $ tree project_dir/ . ├── application.py ├── plugins │ ├── __init__.py │ ├── example_plugin.py │ ├── plugin1.py │ ├── plugin2.py │ └── plugin3 │ ├── sounds │ │ └── test.wav │ └─
$ 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()
每个插件都需要从application.py
导入Manager
实例,并像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时,显然没有打印任何内容。如何使插件在程序启动时自动注册(调用。注册插件()
)
因此,在这一行中,一个更一般化的问题是——如何让python在不实际运行文件的情况下执行文件中全局的一行代码
关于改进插件架构的建议欢迎 您可以使用
\uuuu import\uuuu()
内置程序导入插件,然后在插件文件example\u plugin.py
或\uu init\uuuuu.py
中(如果是目录)包含register\u plugin()
调用
例如,假设这是您的项目结构:
./
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\u manager.py
中,识别插件并将其导入:
从操作系统导入listdir
从os.path导入exists、isdir、basename、join、splitext
def是_插件(文件名):
filepath=join('plugins',filename)
_,ext=splitext(文件路径)
#忽略插件/\uuuu init\uuuuu.py
如果filename='\uuuu init\uuuuu.py':
返回错误
#查找单文件插件
如果ext=='.py':
返回真值
#查找目录中打包的插件
如果isdir(filepath)和存在(join(filepath,'.\u init\u.py')):
返回真值
返回错误
plugin_names=[splitext(p)[0]表示listdir中的p('plugins/'),如果是_plugin(p)]
plugins=[[uuuu导入(plugins.+p)表示插件名称中的p]
输出应类似于:
Plugin 1
Plugin 2
Plugin 3
请注意,在本例中,
plugins
变量包含导入的模块对象列表。严格地说,如果不以某种方式调用它,就无法运行代码。为此,正在运行的程序可以使用
import importlib
因此,一旦找到该文件,您就可以使用以下工具导入该文件:
mod = importlib.import_module(import_name, pkg_name)
如果该文件提供了一个已知函数(在本例中运行),则可以使用以下方法调用它:
mod.Run(your_args)
这适用于Python2.7。版本3可能会有所不同。我希望有一个设置,您只需编写符合特定规范的插件文件,将其放入plugins/dir,然后忘掉它。在init.py或manager.py中硬编码插件名称需要在每次添加/删除插件时修改文件。也不确定是否导入所有.py文件。当一个插件有一个文件夹,其中有多个.py文件时会发生什么?所有这些都将不必要地进口。这就是为什么规范要求插件只在某个地方注册一个主函数。@ParinPorecha这就是为什么我建议您使用
os.listdir
来识别插件文件,然后导入模块(文件名不带.py
扩展名)。此外,您只能在plugins目录中搜索1级深度。一个目录也可以是python模块,如果它包含一个\uuu init\uuuu.py
文件,您可以将register\u plugin()
调用放在该文件中。如何识别插件文件;)?文件夹的名称可以是任何东西,文件名可以是任何东西,我这边唯一的要求是它们在代码中的某个地方注册。@ParinPorecha我已经用一个更完整的例子更新了我的答案。除非您使用某种配置打包每个文件以标识入口点,否则我假设每个*.py
文件或包含插件/
下的init\uuuuuu.py
的目录都是一个插件。