Plugin System

Code-Stücke können hier veröffentlicht werden.
2bock
User
Beiträge: 94
Registriert: Freitag 12. September 2003, 07:58
Wohnort: 50.9333300 / 6.3666700

Mittwoch 20. April 2005, 14:15

Hallo alle zusammen.

Habe aus der Not heraus ein kleines Plugin System geschrieben, aber dann am Ende festgestellt, dass ich es eigenlich gar nicht benötige. Also wer so etwas nutzen zu müssen, der sollte nochmal ganz genau darüber nachdenken, ob dies wirklich so ist. Ich erstelle am ende meiner Entwicklungen mit py2exe immer ein Setup. Wer sich dann mal damit auseinander setzt, wird feststellen, das die *.pyo Dateien gezippt in einer Datei hinterlegt sind. Man bräuchte eigentlich nur die entsprechende *.pyo Datei neu erzeugen und dann auf das Zielsystem kopieren. So und jetzt für alle, die immer noch so was haben wollen der Sourcecode.

Dieser Sourcecode kommt in die Anwendung. Er liest alle konforme Dateien aus einem Ordner ein.

Code: Alles auswählen

import os, os.path, sys, string, imp, traceback
ini_plugin_format = '_plug.py'

class Plugin:
    pluginlist = []

    def __init__(self):
        sys.path.append(os.path.abspath('./plugins'))
        self._importPlugins()
        
    def _importPlugins(self):
        path = os.path.abspath('./plugins')    
        
        for f in os.listdir(path):
            self.pluginlist.append(__import__(f.split('.')[0],globals(),locals(),[]))
            #~ print " ".join(globals().keys())
            #~ print self.pluginlist
    
    def _getPlugins(self):
        for modul in self.pluginlist:
            instance = modul.Test_plug()
            print instance.Function()
            print instance.pluginProp ['name']


if __name__ == '__main__':
    
    plg = Plugin()
    plg._getPlugins()

Und dieser Code kommt in die Plugindatei.

Code: Alles auswählen

class Test_plug:# Muss wie die Datei heissen und die Datei muss auf 
    def __init__(self):
        
        pluginProp = {}
        pluginProp ['name'] = "Beispiel Plugin"
        pluginProp ['version'] = "0.1"
        pluginProp ['format'] = "*.txt"
        pluginProp ['description'] = """laber rababer"""
        pluginProp ['author'] = "Author"
        pluginProp ['author_email'] = "nn@nn.de"
        self.pluginProp = pluginProp 

    def Function(self):
        return 'Dies ist eine Testeingabe'


if __name__ == '__main__':
    
    plg = Test_plug()
    print plg.pluginProp ['name']
    
Viel Spaß mit dem Code.

Greetz from 2bock :wink:
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 4. Juli 2005, 14:53

Mache mir gerade auch Gedanken über ein Plugin/Modul System. Deswegen belebe ich mal diesen Thread...

Gibt es da eigentlich irgendeine offizielle Lösung für???

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Montag 4. Juli 2005, 15:04

jens hat geschrieben:Gibt es da eigentlich irgendeine offizielle Lösung für???
Nein, nicht dass ich wüsste.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 4. Juli 2005, 15:42

Schade, dann bastel ich mir da mal was... Als Anregung nehme ich mal den Code von 2bock...

Hier mal was:
./module/__init__.py

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: UTF-8 -*-

# by jensdiemer.de (steht unter GPL-License)

import sys, os, glob

class module_manager:
    def __init__( self ):
        self.modul_data = {}

    def parse_modules( self ):
        for filename in glob.glob( "*.py" ):
            if filename == "__init__.py":
                # Sich selber auslassen ;)
                continue

            module_name = os.path.splitext( filename )[0]

            try:
                # Infromation's Dict aus Modul holen
                self.modul_data[module_name] = __import__( module_name ).modul_info
            except:
                pass

    ######################################################

    def __getitem__( self, key ):
        return self.modul_data[key]

    def iteritems( self ):
        return self.modul_data.iteritems()

    def __setitem__( self, key, value ):
        self.modul_data[key] = value

    def has_key( self, key ):
        return self.modul_data.has_key( key )

    def __str__( self ):
        return str( self.modul_data )

    ######################################################

    def debug( self ):
        print "Content-type: text/html\n"
        print "<h1>Modul Manager Debug:</h1>"
        print "<pre>"
        for modul_name,modul_info in self.modul_data.iteritems():
            print modul_name
            for section, value in modul_info.iteritems():
                print "\t%s - %s" % (section,value)
            print "-"*80
        print "</pre>"



if __name__ == "__main__":
    mm = module_manager()
    mm.parse_modules()
    mm.debug()
./module/log.py

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: UTF-8 -*-

# by jensdiemer.de (steht unter GPL-License)


modul_info = {
    "description"   : "Wertet die Log-Daten aus der DB aus",
    "admin_needed"  : True, # Benötigt Administrationsrechte
    "url_parameter" : "log_admin"
}

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 5. Juli 2005, 10:03

In dem Zusammenhang hab ich ein altes Posting von Dookie *schnief* gefunden:
http://www.python-forum.de/viewtopic.php?p=12533#12533

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Donnerstag 7. Juli 2005, 20:56

In meiner Variante suche ich ja nach dem "PACKAGE CONTENTS" also den Python-Skripten im eigenen Verzeichnis mit glob.glob( "*.py" )
Aber das muß doch auch anders gehen!

Bsp.:

./index.py
./PyLucid_modules/__init__.py - Ist leer
./PyLucid_modules/ein_modul.py

./index.py

Code: Alles auswählen

import PyLucid_modules
help(PyLucid_modules)
In dem Hilfetext sehe ich das unter "PACKAGE CONTENTS" alle Module im Verzeichnis ./PyLucid_modules/ also das ein_modul
Somit müßte es doch auch für __init__ schon irgendwie sichtbar sein, oder?

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Vortec
User
Beiträge: 52
Registriert: Dienstag 10. Dezember 2002, 11:54

Donnerstag 18. August 2005, 16:05

Wer sehen will wie ich Dookie's Code eingebaut habe:

http://svn.tectic.de/viewcvs/trunk/lib/ ... iew=markup
| [url=http://www.sourceforge.net/projects/propolice/]propolice[/url] | [url=http://del.icio.us/vortec/]bookmarks[/url] | [url=http://www.BlowIRC.net/]irc[/url] | [url=irc://irc.BlowIRC.net/python]#python[/url] |
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mittwoch 24. August 2005, 10:26

Hab da noch ein Problem.
Ich hole mir ja die Modul-Informationen mit:

Code: Alles auswählen

self.modul_data[module_name] = __import__( module_name ).modul_info
Wenn nun aber ein Modul quasi in __main__ schon Anweisungen hat, dann werden diese Ausgeführt. Das möchte ich aber eigentlich nicht! Ich will nur die Informationen aus der Pseudo-Klasse modul_info(). Wie kann ich die erhalten ohne das das Modul "gestartet" wird???

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Sonntag 4. September 2005, 09:35

Deswegen füge in in meine Module den Import-Hook ein:

Code: Alles auswählen

if __name__ == '__main__':
    main()
Dann wird deim Importieren das Modul nicht gestartet.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Sonntag 4. September 2005, 09:45

Ich hab mein Plugin-System (Modul-Manager bei PyLucid) nun eh umgebaut.

Früher war es so, das ich erstmal das ganze Modul-Verzeichnis "durchsucht" hab und die nötigen Informatione aus jedem Modul rausgeholt hab. Das hab ich mit __import__() gemacht.
Nun gehe ich anders vor, nun wird es dann nachgesehen ob ein Modul überhaupt existiert, wenn es benötigt wird.

Ich hab nämlich festgestellt, das ein import des Moduls auch die ganzen import's im Modul selber nach sich zieht. Wenn z.B. urllib, xml.dom.minidom usw. importiert werden, dauert es schon etwas Zeit...

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
henning
User
Beiträge: 274
Registriert: Dienstag 26. Juli 2005, 18:37

Sonntag 4. September 2005, 15:00

Ansonsten spricht ja auch nichts dagegen, Module aus jweils 2 files bestehen zu kassen oder?
Also ein Info-File (z.B. modul_info.py), das halt nichts importiert sondern nur ein paar Strings definiert, die sagen, was das Modul machts, etc...
und dann das eigentliche Modul.

So weißt du vorher schon welche Plugins es gibt mit allen interessanten Einzelheiten und ohne den großen Ladeaufwand.

Wenns unbedingt eine Datei sein soll,
könnte man ja auch überlegen, wichtige Infos in den ersten Zeilen kommentiert unterzubringen, dann nur diese Zeilen einzulesen, Kommentarzeichen entfernen und durch eval() laufen lassen. (Oder direkt selbst parsen)
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Sonntag 4. September 2005, 15:18

Wo wir grad dabei sind, man könnte für Metadaten auch gleich SCALE verwenden. Ich habe es jedoch nicht getestet, wie gut es ist.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Sonntag 4. September 2005, 17:24

@henning: Das wäre auch eine Lösung... Ich finde es allerdings besser, wenn man nur eine Datei editieren muß ;)

Wenn man Metadaten irgendwie parsen muß, egal ob nun mit diesem SCALE oder was eigens gebautes... Es dürfte auch ein wenig Rechenzeit brauchen. Da ist die Frage ob es schneller oder langsamer geht, als ein Modul zu importieren in dem die Daten schon als fertige Daten (Dict o.ä.) vorliegen, es aber nachsich zieht, das diese Modul wieder andere Module importiert, was auch wieder Zeit kostet...

Ich denke ich fahre mit meiner variante schon ganz gut, Module erst dann zu importieren, wenn sie gebraucht werden... Es kann dabei nur passieren, das evtl. der User keine Rechte hat, das Modul auszuführen. In dem Falle war das importieren auch umsonst...
Naja, ich denke das kommt nicht all zu oft vor...

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
uphill
User
Beiträge: 22
Registriert: Sonntag 10. Dezember 2006, 20:17

Samstag 17. März 2007, 20:58

hi,
Bin auch grad dabei sowas zu basteln, aber die da oben funzen ja beide nicht vernünftig. Der erste laded nur die Beschreibung und vorallem muss das Hauptprogramm im sleben verzeihnis ligen wie die Plugins...

deswegen, wie finde ich heraus in was für einem Pfad sich mein aktuelles modul gerade befindet? Und kann ich dann von diesem aus gleich direkt sachen aus dem verzeichnis wo ich bin importeren?
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Samstag 17. März 2007, 21:08

uphill hat geschrieben:deswegen, wie finde ich heraus in was für einem Pfad sich mein aktuelles modul gerade befindet?
So.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Antworten