DEV Community

Dimitar
Dimitar

Posted on

Creating a Plugin Architecture in Python

There are some use-cases where a plugin architecture is needed, I call this "code" plugins but it is quite possible that there is already a word for that. The idea is to 'load' functions or classes that are dynamically created so that you can have the reference to the instances at runtime. I've created 2 solutions for that matter one that is using the __subclasses__ dunder method and one using a decorator.

Solution 1

Repository: https://github.com/syrull/plugin-arch-python/tree/main/Solution-1

SOLUTION-1
│   configuration.py
│   main.py
│   README.md
│   setup.py
│
└───actions
        action_example1.py
        action_example2.py
        __init__.py
Enter fullscreen mode Exit fullscreen mode

Loading the __subclasses__ of the BaseAction class and creating a 'pluggable' classes. The actions can be specified in the configuration.py file in the ACTIONS const. This method is inspired by django's INSTALLED_APPS method.

The call method is a placeholder for the "actions".

To Register an action

  • New python file in actions/ folder
  • Create a class with an appropriate name (ex. ClickAction)
  • Extend the class with BaseAction
  • Add an entry to ACTIONS const located in configuration.py file with the approriate path to the module

After that the function will be available at the register in the main.py file.

$ python main.py
[<class 'actions.action_example1.Example1Action'>, <class 'actions.action_example2.Example2Action'>]
Enter fullscreen mode Exit fullscreen mode

Benchmarks

Measure-Command { python .\main.py }

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 24
Ticks             : 240745
TotalDays         : 2.78640046296296E-07
TotalHours        : 6.68736111111111E-06
TotalMinutes      : 0.000401241666666667
TotalSeconds      : 0.0240745
TotalMilliseconds : 24.0745
Enter fullscreen mode Exit fullscreen mode

Solution 2

Repository: https://github.com/syrull/plugin-arch-python/tree/main/Solution-2

SOLUTION-2
│   main.py
│   README.md
│   register.py
│
└───actions
        action_example1.py
        action_example2.py
        __init__.py
Enter fullscreen mode Exit fullscreen mode

The benefits of this solution are that we have a control over the decorator and we can pass some custom *args, **kwargs to the decorated functions.

To Register an action

  • New python file in actions/ folder
  • Create function with an appropriate name (ex. action_onclick)
  • Decorate the function with register_action decorator
  • Export the function in the __all__ method in actions/__init__.py file

After that the function will be available at the register in the main.py file.

$ python main.py
[<function action_example1 at 0x000001CC3F88D310>, <function action_example2 at 0x000001CC3F88D3A0>]
Enter fullscreen mode Exit fullscreen mode

Benchmarks

Measure-Command { python .\main.py }

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 22
Ticks             : 227803
TotalDays         : 2.6366087962963E-07
TotalHours        : 6.32786111111111E-06
TotalMinutes      : 0.000379671666666667
TotalSeconds      : 0.0227803
TotalMilliseconds : 22.7803
Enter fullscreen mode Exit fullscreen mode

Top comments (0)