Plugin architecture - Plugin Manager vs inspecting from plugins import *

后端 未结 3 735
悲哀的现实
悲哀的现实 2020-12-29 14:55

I\'m currently writing an application which allows the user to extend it via a \'plugin\' type architecture. They can write additional python classes based on a BaseClass o

3条回答
  •  情话喂你
    2020-12-29 15:28

    Since Python 3.6 a new class method __init_subclass__ is added, that is called on a base class, whenever a new subclass is created.

    This method can further simplify the solution offered by will-hart above, by removing the metaclass.

    The __init_subclass__ method was introduced with PEP 487: Simpler customization of class creation. The PEP comes with a minimal example for a plugin architecture:

    It is now possible to customize subclass creation without using a metaclass. The new __init_subclass__ classmethod will be called on the base class whenever a new subclass is created:

    class PluginBase:
        subclasses = []
    
        def __init_subclass__(cls, **kwargs):
            super().__init_subclass__(**kwargs)
            cls.subclasses.append(cls)
    
    class Plugin1(PluginBase):
        pass
    
    class Plugin2(PluginBase):
        pass
    

    The PEP example above stores references to the classes in the Plugin.plugins field.

    If you want to store instances of the plugin classes, you can use a structure like this:

    class Plugin:
        """Base class for all plugins. Singleton instances of subclasses are created automatically and stored in Plugin.plugins class field."""
        plugins = []
    
        def __init_subclass__(cls, **kwargs):
            super().__init_subclass__(**kwargs)
            cls.plugins.append(cls())
    
    class MyPlugin1(Plugin):
        def __init__(self):
            print("MyPlugin1 instance created")
    
        def do_work(self):
            print("Do something")
    
    class MyPlugin2(Plugin):
        def __init__(self):
            print("MyPlugin2 instance created")
    
        def do_work(self):
            print("Do something else")
    
    for plugin in Plugin.plugins:
        plugin.do_work()
    

    which outputs:

    MyPlugin1 instance created
    MyPlugin2 instance created
    Do something
    Do something else
    

提交回复
热议问题