Вопрос

I would like to make a plugin system for my script.

How plugins are loaded

The plugins are python modules stored in a specified folder.

I import the modules with this code:

class Igor:

    # ...

    def load_plugins(self):

        for file in os.listdir(self.plugins_folder):

            try:
                __import__(file)
            except Exception as error:
                sys.exit(error)

    # ...

The variable I want to make available in the plugins

I have a variable named igor who is an instance of Igor:

if __name__ == "__main__":

    # ...

    igor = Igor()

    # ...

What I want the plugins developers able to do

I want to make plugins development easy and igor have all the methods needed to make it easy.

At best it should be something like this (in __init__.py):

from plugins.files.files import Files

igor.register_plugin("files", Files())

How can I do that?

I really don't see how to do this globals() display igor in my main script but there is nothing in the globals from the menu (as expected from a module, it is sandboxed I supposed).

Any ideas?

Это было полезно?

Решение

You will need to change the load_plugins method on your Igor class:

    def load_plugins(self):
        if not os.path.exists(self.plugins_folder):
            os.makedirs(self.plugins_folder)

        plugin_folder_content = os.listdir(self.plugins_folder)

        for content in plugin_folder_content:
            content_path = os.path.join(self.plugins_folder, content)
            if os.path.isdir(content_path):
                plugin_entry_point_path = os.path.join(content_path, "__init__.py")
                if os.path.exists(plugin_entry_point_path):
                    try:
                         with open(plugin_entry_point_path, 'r') as file:
                             sys.path.insert(1, content_path)
                             exec(compile(file.read(), "script", "exec"), {"igor": self, "IgorPlugin": IgorPlugin, 'path': content_path})
                             sys.path.remove(content_path)
                    except Exception as exc:
                         sys.exit(exc)

This creates another problem: as we are excecuting the init.py files on each module, defined on each subdirectory, you can't import files easily, that's why I'm passing the path variable, to import files manually, this is an example of a imaginary init.py file which imports files.py plugin:

import os

files_path = os.path.join(path, "files.py")

exec(compile(open(files_path).read(), "script", "exec"), {"igor": igor, "IgorPlugin": IgorPlugin})
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top