I’m trying to create a plugin framework similar to yapsy (unfortunately yapsy is not python3 compatible).
My code looks like this:
root
main.py
plugins/
__init__.py
PluginManager.py
UI/
__init__.py
textui.py
In PluginManager.py I defined the following class:
class PluginMetaclass(type):
def __init__(cls, name, base, attrs):
if not hasattr(cls, 'registered'):
cls.registered = []
else:
cls.registered.append((name,cls))
class UI_Plugins(object):
__metaclass__ = PluginMetaclass
#...some code here....
def load():
#...some code here too...
if "__init__" in os.path.basename(candidate_filepath):
sys.path.append(plugin_info['path'])
try:
candidateMainFile = open(candidate_filepath+".py","r")
exec(candidateMainFile,candidate_globals)
except Exception as e:
logging.error("Unable to execute the code in plugin: %s" % candidate_filepath)
logging.error("\t The following problem occured: %s %s " % (os.linesep, e))
if "__init__" in os.path.basename(candidate_filepath):
sys.path.remove(plugin_info['path'])
continue
where candidate_filepath contains the plugin path.
textui.py contains the following:
from root.plugins.PluginManager import UI_Plugins
class TextBackend(UI_Plugins):
def run(self):
print("c")
When I try to load the plugin I get this error:
No module named plugins.PluginManager
How can I solve this problem?
The import statement
doesn’t work because
rootis not a package.However, if the application is started with
then
rootdoesn’t actually need to be a package.All you need to do is change the the import statement in
textui.pytoand everthing should work correctly.
The reason this works, is because the directory of the currently running script is always automatically added to the start of
sys.path. In your case, this will be theroot, and sincepluginsis a package within that directory, it can be directly imported from anywhere within your application. So, as long as yourmainscript remains where it is, there should be no need for any other path manipulations.