Implementing a plug-in mechanism
Thomas Passin
list1 at tompassin.net
Wed Mar 15 15:42:10 EDT 2023
On 3/15/2023 2:45 PM, dn via Python-list wrote:
> On 16/03/2023 01.47, Loris Bennett wrote:
>> I have written a program which, as part of the non-core functionality,
>> contains a module to generate email. This is currently very specific
>> to my organisation, so the main program contains
>>
>> import myorg.mailer
>>
>> This module is specific to my organisation in that it can ask an
>> internal server to generate individualised salutations for a given UID
>> which is known within the organisation.
>>
>> I want to share the code with other institutions, so I would like to
>>
>> 1. replace the organisation-specific mailer with a generic one
>> 2. allow an organisation-specific mailer to be used instead of the
>> generic one, if so desired
>
> This may call for the plug-in pattern, ie the user will choose whether
> to plug-in the specific, or the generic, module.
>
> In Python, we would tend to use a Dependency Injection approach (one of
> Uncle Bob's SOLID principles).
[snip]
Here is (slightly modified) plugin code I'm using in one project. You
could use a naming convention to see if there is a plugin for a specific
organizations, or each module could contain a UID variable which you
could inspect to find the desired one. This code is under the MIT
License, so feel free to adapt it if you like.
def import_all_plugins(plugins_import_list, plugin_dir):
"""Import modules from the plugins directory and return a list of them.
If plugins_import_list is not empty or None, only import the ones
listed there. Otherwise import all ".py" files.
RETURNS
a list of successfully imported modules.
"""
modules = []
if not plugins_import_list:
plugins_import_list = []
for root, dirs, files in os.walk(plugin_dir):
if root == plugin_dir:
break
for f in files:
f, ext = os.path.splitext(f)
if ext == '.py':
plugins_import_list.append(f)
for f in plugins_import_list:
try:
mod = importlib.import_module(f'plugins.{f}')
modules.append(mod)
except ImportError as e:
print(f'{__name__}: {f} plugin: {e}')
continue
return modules
More information about the Python-list
mailing list