Python; How to import methods to a class 'pluginstyle'?
I'm 开发者_StackOverflowtrying to make a class that imports its methods from plugin-like modules.
What I want for this class is for it to be able to import functions/vars from modules that are stored in a separate folder, i.e 'plugins'. Is this possible?
i know about __import__()
, but how can i use it to import so they belong to this class?
lets say i have the following modules in the 'plugins' folder:
plugins/pluginA.py
plugins/pluginB.py
In these modules i have functions etc. And i want to be able to import and access them in the class. Maybe something like:
MyClass.pluginA.some_function_from_A()
MyClass.pluginB.some_function_from_B()
or perhaps like this
MyClass.some_function_fromA()
MyClass.some_function_fromB()
I would break the problem up into two parts: turning a list of files into a list of modules, then extending the class to include functions from those modules.
Brett Cannon has covered how to import a module from just a file path, so I won't duplicate that here… Although I'll suggest that you check out the glob module.
Second, how to extend a class to include the functions from a plugin. I would use something like this:
def extend(obj, plugin_modules):
for module in plugin_modules:
for export_name in dir(module):
export = getattr(module, export_name)
if callable(export):
setattr(obj, export_name, export)
class MyClass(object):
… code …
extend(MyClass, plugin_modules)
HOWEVER, I will warn you that it's unlikely that this is what you want, as the “plugin” functions on MyClass
won't behave exactly like native methods… If you give more information about what you're trying to do, I might be able to give a more helpful answer.
I've been experimenting and rummaging around with google and i've come up with a solution that could work thanks to the tip about setattr
and getatt
from David Wolever and This page by Jesse Noller.
Here's what i have so far, and it appears to be working, needs cleanup and fine tuning though.
class MyClass(object):
def __init__(self):
pass
def import_plugins(self):
plugins_to_import = []
attribs_to_exclude = ['__builtins__', '__doc__', '__file__', '__name__', '__package__']
plugins = []
plugins_dir = './plugins'
# add the plugins directory to path
if os.path.isdir(plugins_dir):
sys.path.append(plugins_dir)
else:
print '%s is not a directory!' % (plugins_dir)
# make a list of the plugins to import
for plugin_file in os.listdir(os.path.abspath(plugins_dir)):
#print plugin_file
plugin_file_name, plugin_file_extension = os.path.splitext(plugin_file)
if plugin_file_extension == '.py':
plugins_to_import.append(plugin_file_name)
# import the plugins to a list
for plugin in plugins_to_import:
plugins.append(__import__(plugin))
# add the attributes to self
for plugin in plugins:
for attribute in dir(plugin):
if attribute not in attribs_to_exclude:
self.__setattr__(attribute, getattr(plugin, attribute))
One problem now is to figure out how to pass self
to the imports...
精彩评论