0

我用 Python 3 编写。

我想为我的程序添加插件支持。我不想使用繁重的框架,所以我决定自己写一个最小的框架。

顺便说一句,插件需要按时间运行。重新运行时,我并不总是卸载和加载插件——插件会丢失所有数据。

我的文件夹结构在这里:

interfaces/
├── dummy
├── gmail
│   ├── __init__.py
│   └── __pycache__
│       └── __init__.cpython-33.pyc
└── hello
    ├── __init__.py
    └── __pycache__
        └── __init__.cpython-33.pyc

然后,我写了一段代码来加载和执行插件:

#!/usr/bin/python3
import os
import imp

INTERFACES_FOLDER = './interfaces'
MAIN_MODULE = '__init__'

def search_plugins():
    plugins = []
    plugins_folders = os.listdir(INTERFACES_FOLDER)

    for i in plugins_folders:
        plugin_folder = os.path.join(INTERFACES_FOLDER, i)

        if not os.path.isdir(plugin_folder):
            continue
        if not MAIN_MODULE + '.py' in os.listdir(plugin_folder):
            continue

        info = imp.find_module(MAIN_MODULE, [plugin_folder])
        plugins.append({'name': i, 'info': info})
    return plugins


def load_plugin(plugin):
    return imp.load_module(MAIN_MODULE, *plugin["info"])


plugins_list = search_plugins()
plugins = []

for i in plugins_list:
    module = load_plugin(i)
    print(module)
    plugins.append(module)

print(plugins)

输出:

# it works!
<module '__init__' from './interfaces/gmail/__init__.py'>
<module '__init__' from './interfaces/hello/__init__.py'>

# what's wrong?
[<module '__init__' from './interfaces/hello/__init__.py'>, 
 <module '__init__' from './interfaces/hello/__init__.py'>]

如您所见,当我加载插件时,一切正常。但是当我将它们附加到列表时,不同的模块将变成同一个。

怎么了?

4

1 回答 1

1

您导入不同的模块,但名称相同(它们都称为“ init ”)。当您导入第二个模块时,Python 会注意到您已经导入了一个名为“ init ”的模块并返回它。

您应该导入的模块是“gmail”和“hello”模块。那可能行得通。

但是,我敦促您重新考虑编写自己的插件系统。这真的不是那么容易。快速搜索会发现几个插件系统,有些是轻量级的,有些不是那么多。大多数已被放弃,这表明这并不像您想象的那么容易。

Python 中可能使用最广泛、最灵活和最古老的插件系统是Zope 组件架构。另请参阅文档。请注意,在 Python 3 中,您使用类装饰器而不是类主体语句。

另一个流行的插件系统是 Distribute 的“入口点”。这是相当轻量级的,虽然我不知道你是否可以用它加载或卸载插件。

其他我从未看过的还有Yapsy,一个叫做“Plugins”的似乎被废弃了,另一个叫做“PyPlugin”也被废弃了,还有一个叫做“ easy_plugins ”,它看起来很新,但还没有被废弃。

是插件管理器的示例代码

于 2012-12-05T11:12:33.127 回答