Eine .py im Unterordner aufrufen und starten

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Fabian Kochem
User
Beiträge: 36
Registriert: Mittwoch 5. April 2006, 14:11
Wohnort: Köln

Wenn ich kurz was dazu einwerfen darf:
Über das (mitgelieferte) Modul imp erhälst du direkten Zugriff auf die Implementation des "import"-Statements. Damit sollte es relativ einfach sein, einen kleinen Plugin-Manager zu basteln.
Habe ich selbst auch schonmal in einem Projekt benutzt, hinterher konnte man über die Konsole sogar zur Laufzeit die Plugins neu einlesen, sodass nicht jedes Mal die komplette Applikation neu initialisiert werden musste. Wenn du mit dem Modul nicht klarkommst, kann ich den Quellcode nochmal raussuchen.
Benutzeravatar
Batt0sa1
User
Beiträge: 15
Registriert: Montag 21. April 2008, 23:15

Fabian Kochem hat geschrieben:(...) kann ich den Quellcode nochmal raussuchen.
Na zu dem Angebot sag ich doch nicht "Nein" :D
Funzt nämlich doch nicht ganz so wie es soll...
(momentan wird immer das zuletzt importierte Modul aufgerufen)

Ein Beispiel würde mir da stark weiterhelfen 8)
Benutzeravatar
Batt0sa1
User
Beiträge: 15
Registriert: Montag 21. April 2008, 23:15

Ich will euch ja meine Lösung nicht vorenthalten :D

Das Problem war, dass ich zwar alle Module importieren, aber sie nicht im wx.Menu aufrufen konnte... Es wurde immer nur das zuletzt importierte Modul ausgeführt (was auch logisch ist, da dem "self.plugin" ja immer wieder neue Werte hinzugefügt wurden)

Egal...
Ich hab es jetzt mit einer Liste für alle importierten Module gelöst, die Ids verglichen und das Ganze in eine Klasse gefügt :)
Irgendwie empfinde ich es zwar ein weinig als Frickelei *g* (gibt sicher elegantere Lösungen), aber es funzt bisher ganz gut...
Um das Menü zu füllen, wird die Klasse Plugins (s.u.) initialisiert:

Code: Alles auswählen

 list = Plugins().Pluginmenulist(parent)
Die Klasse:

Code: Alles auswählen

class Plugins():
    ''' diese Klasse importiert die Plugins in die Menüleiste und (später) auch in die Toolbar 
    ToDo: die benötigten Übergabewerte der Startfunktion möglicherweise auslesen
            '''
    def startplugin(self, event):
        menubar = self.parent.GetMenuBar()
        #finde Menüeintrag, mit dem Namen "[1]"  
        for _ in self.pluginlist:
            '''getriggerte ID des events abgleichen mit allen Einträgen im Pluginmenü
            sobald ein Menüname gefunden wurde der PlugIn starten'''
            id = menubar.FindMenuItem('Plugin',_[1])  
            if  event.GetId() == id:
                    #print menubar.GetLabel(id)
                    plugin = _[0]
                    plugin.Start(self.parent)
                    break
            else:
                continue
        event.Skip()       
        
    def Pluginmenulist(self, parent): 
        '''in dieser Funktion werden die Plugin-Menüeinträge erzeugt ''' 
        logging.debug('Pluginmenu wird erstellt')
        list = []
        self.pluginlist = []
        path = os.path.abspath(os.path.join(os.path.curdir, u"plugins"))    
        i = 0   
        self.parent = parent
        self.plugin = None
        for foldername in os.listdir(path):                                 #iterieren über den pluginordner
            if foldername.startswith(".") or (foldername.endswith(".py")     #versteckte und 
                                          or foldername.endswith(".pyc")):   #py - Dateien ausblenden
                continue 
            try:
                #in jedem Ordner die Readme auslesen
                logging.debug('Modul '+ foldername +' wird geladen')
                f_path = os.path.join(path, foldername, 'Readme.txt')
                file = open(f_path,"r")
                Beschreibung = file.readlines(1)
            except:
                logging.debug(u"keine Readme.txt gefunden in "+ f_path + " gefunden")
            
#------------import plugins------------------------------------------------------------
            #die Datei start.py aus /plugins/Plugin-name importieren
            pluginort =  "plugins."+foldername
            #__import__ akzeptiert Strings als Übergabewert
            try:
                self.plugin = __import__("plugins."+foldername+".start", globals(), locals(), ['start'])
            except:
                plugin = None
                logging.debug(u"konnte kein Startmodul in "+ pluginort + " für Plugin" + foldername + " finden")
            try:
                #Listeneintrag für das PluginMenu hinzufügen
                list.append([str(foldername), str(Beschreibung), self.startplugin, '', '', True]) 
            except:
                logging.debug(u"konnte Modul "+ foldername + " nicht hinzufügen")
            self.pluginlist.append([self.plugin, str(foldername)]) #speichert alle importierten Startfunktionen
        logging.debug('keine weiteren Plugins zum importieren gefunden')
        return list
Und die zurückgegeben Liste wird dann in der Form:

Code: Alles auswählen

plugin = menu.Append(wx.NewId(),list[0],list[1])
parent.Bind(wx.EVT_MENU, list[2], plugin)
in einer "for" - Schleife verwendet...
Den ganzen Code kann ich aber nicht auseinander klamüsern, da ich ja nur die oben genannte Schnittstelle geschrieben habe 8)
Falls aber jemand vor dem selben Problem steht und trotz allem nicht weiter kommt, versuche ich es zur Not aber gerne nochmal...
^^

Veglichen mit meinem Startversuch ist es ja doch ein wenig größer geworden. Auf jeden Fall Danke für die Tipps, ich wäre sonst wohl nur sehr schwer auf den Trichter gekommen :)
THX @ all
Fabian Kochem
User
Beiträge: 36
Registriert: Mittwoch 5. April 2006, 14:11
Wohnort: Köln

Sorry, ein bisschen verspätet - aber vielleicht ja doch noch ganz interessant:

Code: Alles auswählen

    def loadPlugin(self, filename):
	"""
	    Try to load a plugin in plugins/filename via imp.
	"""
	
	# File has .py extension
	if filename[-3:] == ".py":
	    plugin_file = filename[:-3]
	    
	    # Import file via imp and try to load class Plugin
	    (n, f, s) = imp.find_module(plugin_file, ['plugins'])
	    inst = imp.load_module(plugin_file, n, f, s).Plugin(self.propolice)
Ein Plugin sähe z.B. so aus und läge in ./plugins/auth.py:

Code: Alles auswählen

class Plugin:
    def __init__(self, propolice):
        """ """
        self.propolice = propolice
        self.propolice.plugins.registerCommand("auth", self.auth, require_channel=0, require_privmsg=1, require_level="none")
        self.propolice.plugins.registerModule("auth_logout", self.logout, re.compile("^:(.*)!.*@.* QUIT .*$"))
Aufruf mit .loadPlugin("auth.py"), in inst hättest du dann die Instanz aus auth.py.
Antworten