Python 如何在不调用文件的情况下运行全局代码

Python 如何在不调用文件的情况下运行全局代码,python,Python,我正在编写一个python应用程序,它允许用户编写自己的插件并扩展我提供的核心功能- $ tree project_dir/ . ├── application.py ├── plugins │   ├── __init__.py │   ├── example_plugin.py │   ├── plugin1.py │   ├── plugin2.py │   └── plugin3 │   ├── sounds │   │   └── test.wav │   └─

我正在编写一个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()
每个插件都需要从
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
的目录都是一个插件。