473,586 Members | 2,555 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Best practices for dynamically loading plugins at startup

Dear coders...

I'm working on an application that is supposed to support "plugins".
The idea is to use the plugins as packages like this:

Plugins/
__init__.py
Plugin1.py
Plugin2.py
Plugin3.py

When the application starts up I want to have these modules loaded
dynamically. Users can put their own plugin modules into the
Plugins/ directory and the application should know about it.

Since I don't know which plugins have been put into that directory
I cannot just "import Plugin1, Plugin2, Plugin3" in the "__init__.p y".
So I need to find out the *.py there and load them during startup.
I could do that with a "walk" over that directory.

Each plugin is supposed to be a class derived from a general
"Plugin" superclass. I just don't know how to 'register' every
plugin. The main application needs to know which plugin classes
there are. On IRC I was recommended walking through all objects
and finding out if the class is a subclass of "Plugin". Another
person recommended using metaclasses to automatically register
the plugin in a global list.

Since I have only little real-life Python knowledge I wonder what the
best practice for this kind of problem is.

I looked at the "supybot" IRC bot to get an idea how plugins are handled
there. Unfortunately it was still a bit over my (python) head.

Regards
Christoph
--
~
~
~
".signature " [Modified] 3 lines --100%-- 3,41 All
Sep 25 '05 #1
5 3173
Christoph Haas napisa³(a):
Since I don't know which plugins have been put into that directory
I cannot just "import Plugin1, Plugin2, Plugin3" in the "__init__.p y".
So I need to find out the *.py there and load them during startup.
I could do that with a "walk" over that directory.


See entry for __import__ at
http://www.python.org/doc/2.3/lib/built-in-funcs.html

--
Jarek Zgoda
http://jpa.berlios.de/
Sep 25 '05 #2
Christoph Haas wrote:
Dear coders...

I'm working on an application that is supposed to support "plugins".
The idea is to use the plugins as packages like this:

Plugins/
__init__.py
Plugin1.py
Plugin2.py
Plugin3.py

When the application starts up I want to have these modules loaded
dynamically. Users can put their own plugin modules into the
Plugins/ directory and the application should know about it.

Since I don't know which plugins have been put into that directory
I cannot just "import Plugin1, Plugin2, Plugin3" in the "__init__.p y".
So I need to find out the *.py there and load them during startup.
I could do that with a "walk" over that directory.

Each plugin is supposed to be a class derived from a general
"Plugin" superclass. I just don't know how to 'register' every
plugin. The main application needs to know which plugin classes
there are. On IRC I was recommended walking through all objects
and finding out if the class is a subclass of "Plugin". Another
person recommended using metaclasses to automatically register
the plugin in a global list.

Since I have only little real-life Python knowledge I wonder what the
best practice for this kind of problem is.

I looked at the "supybot" IRC bot to get an idea how plugins are handled
there. Unfortunately it was still a bit over my (python) head.


I recently came up against this exact problem. My preference is to have
the plugin writer call a method to register the plugins, as this allows
him the most control. Something along these lines:

class A_plugin(Plugin ):
...

class Another_plugin( Plugin):
...

register( A_plugin )
register( Another_plugin, optional_custom _registration_p arameters )
I also like the Mark Pilgrim approach of having the plugins follow a
strict naming convention, then searching for them with hasattr or by
grepping each plugin module's namespace. E.g., I have a build script
written in python that I use instead of the "make" utility; for each
target, I define a method called make_<target> in my plugin module, like
this:

function = "make_%s" % target
if hasattr(module, function):
getattr(module, function)()
else:
print >>sys.stderr, 'Unknown target "%s"' % target
Sep 26 '05 #3
I wrote this one:
--------------------------------------
def load_plugin(sel f, plugin, paths):
import imp
# check if we haven't loaded it already
try:
return sys.modules[plugin]
except KeyError:
pass
# ok, the load it
fp, filename, desc = imp.find_module (plugin, paths)
try:
mod = imp.load_module (plugin, fp, filename, desc)
finally:
if fp:
fp.close()
# instantiate and put into basket
clazz = mod.main(self.c onfig)
if "input" in clazz.types:
self.inputs.app end(clazz)
if "parser" in clazz.types:
self.parser.app end(clazz)
if "output" in clazz.types:
self.outputs.ap pend(clazz)
--------------------------------------
The imp module is the key:
http://docs.python.org/lib/module-imp.html

The parameters for the load module function, are found by look through
the directory. So my plugins had a convention:
They have a class called main, which is initialized with one argument,
the config object.

That is quite a simple plugin system. You can check out the whole thing
here:
https://developer.berlios.de/projects/feedisto/

Sep 26 '05 #4
On Sun, Sep 25, 2005 at 11:33:03PM -0400, Jeff Schwab wrote:
I recently came up against this exact problem. My preference is to have
the plugin writer call a method to register the plugins, as this allows
him the most control. Something along these lines:

class A_plugin(Plugin ):
...

class Another_plugin( Plugin):
...

register( A_plugin )
register( Another_plugin, optional_custom _registration_p arameters )


I like the idea. And "supybot" seems to do just that. What would the
"def register:" do? Maintain a global list of registered plugins?
I didn't like the idea of having global variables. Or would register
be a method of some "main" class? How would I access that?

Thanks to everybody else who posted ideas on my problem. I'm trying
all the proposals to get an idea of which approach works best.

Regards
Christoph
--
~
~
~
".signature " [Modified] 3 lines --100%-- 3,41 All
Sep 26 '05 #5
Christoph Haas wrote:
On Sun, Sep 25, 2005 at 11:33:03PM -0400, Jeff Schwab wrote:
I recently came up against this exact problem. My preference is to have
the plugin writer call a method to register the plugins, as this allows
him the most control. Something along these lines:

class A_plugin(Plugin ):
...

class Another_plugin( Plugin):
...

register( A_plugin )
register( Another_plugin, optional_custom _registration_p arameters )

I like the idea. And "supybot" seems to do just that. What would the
"def register:" do? Maintain a global list of registered plugins?
I didn't like the idea of having global variables. Or would register
be a method of some "main" class? How would I access that?


The registry clearly has to be shared between modules, so I think it's
best to make it a module-level variable. In the simple-minded code
below, I've stored it in the "plugins" module. A better choice might be
the module that defines your plugins' common base class, if they have one.
# BEGIN framework.py
if __name__ == "__main__":
import plugins
print plugins.plugin_ registry
# END framework.py

# BEGIN plugins.py
# Define some plugins.

class A_plugin(object ):
def __init__(self):
print "A_plugin() "

class Another_plugin( object):
def __init__(self):
print "Another_plugin ()"

# Register the plugins.

import registry

plugin_registry = registry.Regist ry()
plugin_registry .register(A_plu gin)
plugin_registry .register(Anoth er_plugin)
# END plugins.py

# BEGIN registry.py
class Registry(object ):
"Each instance may be used to store a set of objects."

def __init__(self):
"Initialize an empty registry."
self.registered _objects = set()

def register(self, o):
"Add an object to the registry."
self.registered _objects.add(o)

def __repr__(self):
return "Registry Contents:\n\t" + \
"\n\t".join(rep r(o) for o in self.registered _objects)
# END registry.py
Sep 27 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
5002
by: Benjamin | last post by:
Hi, I'm currently writing a Web Services that interacts with a database. To allow me to use not just one database provider (for example, I could use MS Access, SQL Server or MySQL), the Web Service dynamically loads up an assembly that implements an Interface I called IDatabase. To load the assembly and create an object, I wrote this...
0
1084
by: Nejat Ozsu | last post by:
Hi, Short of emitting dynamically assemblies I would like to be able to add metdadata dynamically at run to a property of my serialization class based on dynamically loaded plugins. I dynamically load plugins and then deserialize configuration files for said plugins. Plugins provide "action" classes and "action definition classes" derived...
0
1859
by: David Levine | last post by:
This is a lengthy post; please bear with me... This will be a large system with dozens of plugins. In addition to plugins developed internally there will be 3rd parties that will write their own and integrate them into our application. I will be managing the identification and loading of these plugins. In addition, there are a number of...
0
2556
by: Thibaut | last post by:
Hi, What are the recommended practices on how to use the __crt_dll_initialize() and __crt_dll_terminate() calls described at http://support.microsoft.com/?id=814472 in order to circumvent the mixed-dll bug ? I implemented the ManagedWrapper class, as described in the kb. Calling init before anything else, then calling terminate after...
10
3432
by: jojobar | last post by:
Hello, I am trying to use vs.net 2005 to migrate a project originally in vs.net 2003. I started with creation of a "web site", and then created folders for each component of the site. I read somewhere that each folder under the "web site" is compiled in separate assembly. I however, did not find that the "web site" creation in vs.net...
6
6870
by: Dan Dorey | last post by:
I actually have two questions here, but I'll start by giving an outline of what I'm trying to do. I'm building an app with a simple plugin architecture (all in the same app domain). I have each plugin in a separate sub-dir inside a "Plugins" directory. Each plugin consists of at least two DLLs (a controller and a driver). However, most...
0
2311
by: npthomson | last post by:
Hi all, This could get a bit complicated but I'll try to be as clear as possible. I've written an application that discovers plugins at runtime using reflection from a subdirectory of the application, eg: In the directory the application is installed to: \application.exe \plugins\plugin1.dll
7
1957
by: hg | last post by:
Hi, I have the following problem. I find in a directory hierarchy some files following a certain sets of rules: ..../.../../plugin/name1/name1.py ..... ..../.../../plugin/namen/namen.py
8
2019
by: Flavio | last post by:
Hi, Nowadays the addition of functionality to programs by means of plugins is very frequent. I want to know the opinions of experienced Python developers about the best practices when it comes to developing a plugin system for a Python package. Should plugins be modules in a separate package?
0
7839
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
8202
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
8338
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
0
8216
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
1
5710
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
3837
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
1
2345
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1449
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
1180
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.