Reputation: 11605
I'm trying to create a 'plugin' system, where placing a python file (or package) inside a 'plugins' folder, and reloadings the script will dynamically call the functions inside those files.
I have the following file structure
main.py
plugins -
|- test.py
|- status.py
I import the test.py/status.py modules like so:
sys.path.append('plugins')
plugins_list = os.listdir('plugins')
plugins_list.remove('__pycache__') # prevenet error from being raised
for module in plugins_list:
importlib.import_module('plugins.'+module[:-3])
print("Imported {}".format('plugins.'+module[:-3]))
Script runs fine. I try print(sys.modules.keys())
and plugins.test
and plugins.status
have indeed been imported. However now when I attempt to call any functions inside, a name error is raised NameError: name 'plugins' is not defined
This takes me to Python custom module name not defined where they explain that plugins.status.get_status()
will not work. I somehow have to import it differently. The issue is that I've used importlib so I'm not sure how to achieve that.
I've looked at the documentation page:
importlib.import_module(name, package=None)
Import a module. The name argument specifies what module to import in absolute or relative terms (e.g. either pkg.mod or ..mod). If the name is specified in relative terms, then the package argument must be set to the name of the package which is to act as the anchor for resolving the package name (e.g. import_module('..mod', 'pkg.subpkg') will import pkg.mod).
The
import_module()
function acts as a simplifying wrapper aroundimportlib.__import__()
. This means all semantics of the function are derived fromimportlib.__import__()
. The most important difference between these two functions is thatimport_module()
returns the specified package or module (e.g. pkg.mod), while__import__()
returns the top-level package or module (e.g. pkg).
It seems as if __import__()
would solve my problem, however it recommends I do not use that.
Additionally I feel like defining something as the second importlib arguement may sort the problem, however I'm not sure what
How do I make it so that the functions could be run?
Upvotes: 0
Views: 269
Reputation:
When you are running importlib.import_module('plugins.'+module[:-3])
the value that is getting returned is the imported module. It's not being assigned to anything so it's getting cleaned up almost as soon as it's imported. You can dynamically add to the namespace, but it's not recommended.
Try something like this, where you're assigning the imported module to a dictionary, that you can then reference the module via the dictionary based on the module name:
plugin_dict = {}
for module in plugins_list:
modname = module[:-3]
plugin_dict[modname] = importlib.import_module('plugins.'+modname)
print("Imported {}".format('plugins.'+module[:-3]))
plugin_dict['status'].get_status()
Upvotes: 2