Kamalpreet Singh
Kamalpreet Singh

Reputation: 55

Python plugin architecture where plugins are packages

I am trying to create a python application that can be extended with plugins.

For testing I've tried to create a plugin with the following structure:

plugin_name
├── __init__.py
├── utils.py
└── config.py

The plugin class that I need is located in plugin_name.__init__.py, but ___init__.py uses utils.py.

I am using the following code to import __init__.py:

import os

module_path = "path to __init__.py"
package_name = os.path.basename( os.path.dirname(path) )
spec = importlib.util.spec_from_file_location(package_name, path)
plugin_module = importlib.util.module_from_spec(spec)

spec.loader.exec_module(plugin_module )

If __init__.py imports utils.py as such:

import utils.py

It throws ModuleNotFoundError: No module named 'utils'

If __init__.py imports utils.py as such:

import utils.py

It throws ImportError: attempted relative import with no known parent package

So it's obvious that the import code I'm using doesn't recognize the package and only imports the specific file I specify without any metadata of the folder it is in or the other files in the same directory.

Is there a way to import packages like this?


I'm looking into pkgutil and I can see that using pkgutil.walk_modules, I can identify all the packages in the plugin. I'm wondering if I can use this to import the plugins I want, but I can't find any examples or documentation that would suggest this.

Upvotes: 1

Views: 1465

Answers (1)

Kamalpreet Singh
Kamalpreet Singh

Reputation: 55

If the plugin directory looks as such:

path_to_plugin
└── plugin_name
    ├── __init__.py
    ├── utils.py
    └── config.py
import pkgutil

path = 'path_to_plugin'

modules = []
for package in pkgutil.iter_modules(path):
    finder, name, ispkg = package
    spec = finder.find_spec(name)
    module = spec.loader.load_module(name)
    modules.append(module)

This code loads packages dynamically inside a directory.

If there is a better answer, please share.

Upvotes: 1

Related Questions