Seite 1 von 1

Module dynamisch einbinden

Verfasst: Sonntag 10. Oktober 2004, 16:09
von Eleetchen
Hallo

Ich möchte ein Modulbasiertes Python-Script erstellen und bin da auf ein Problem gestossen. Denn ich möchte zur Laufzeit des Scriptes Module nachladen wenn sie gebraucht werden. Und am besten auch wieder entladen. Die Frage ist nun wie ich das mach?

Also als Beispiel würd das im Idealfall so aussehen:

Code: Alles auswählen

# Lese aus Datei/Verzeichnis aus was für Module vorhanden sind.

# Lese aus der Konfiguration (SQL-Datenbank) welche Module geladen werden sollen

# Lade Modul und frage ein paar Einstellungen von dem Modul ab, sollte ungefähr so aussehen (is eher pseudocode):

while str in modules:
  import str
  if str.module_command_processing:
    # Tu irgendwas....
  else
    # Tu was anderes
Also so ähnlich müsste das funktionieren, es ist mir klar das obiger Code nicht funktioniert und nicht funktionieren kann. Doch hab ich bisher keine Lösung für dieses Problem gefunden. Das Programm soll fähig sein während der Laufzeit neue Module zu laden und zu initialisieren um seine funktionalität zu erweitern on the fly und am besten auch Module aus dem Speicher zu entfernen und zu deinitialisieren.. natürlich on the fly.

see ya, Eleetchen

Verfasst: Sonntag 10. Oktober 2004, 16:57
von mawe
Hi!

Code: Alles auswählen

module = ["sys","os"]
for i in module:
    exec "import %s" % i
Meinst Du so etwas?

Gruß, mawe

Verfasst: Sonntag 10. Oktober 2004, 16:58
von Vortec
Befass dich mal mit der Funktion "reload", oder schau dir den Code von meinem Bot an, der genau das macht. (-> Signatur)

Verfasst: Sonntag 10. Oktober 2004, 17:02
von mawe
Hi!

Ob reload() wirklich das richtige ist? In der Doku steht
... The module must have been successfully imported before.
Gruß, mawe

Verfasst: Sonntag 10. Oktober 2004, 17:23
von Vortec
Ansonsten auch gerne imp.
This module provides an interface to the mechanisms used to implement the import statement.

Verfasst: Sonntag 10. Oktober 2004, 17:57
von Dookie
Hi,

na wenn schon __import__


Gruß

Dookie

Verfasst: Dienstag 12. Oktober 2004, 17:17
von Eleetchen
Hallo :-)

Danke erstmal für die schnellen Antworten. Bin mich grad am einlesen in diese Dinge und guck mal was sich damit machen lässt. Bisher hab ich nur noch keinen Weg gefunden Module wieder zu entladen. Aber das wird auch hinzukriegen sein, auch wenn ich dafür n Kern in C schreiben muss der die Python-Module verwaltet.

see ya, Eleetchen

Verfasst: Dienstag 12. Oktober 2004, 17:58
von Milan
Tja, zum entladen weiß ich auch nix so direkt. Eigentlich sollte es helfen, alle Referenzen auf das Modulobjekt zu löschen und es dann noch aus sys.modules entfehrnen, dann wird es automatisch entfehrnt.

neues Problem

Verfasst: Freitag 22. Oktober 2004, 10:41
von pSy
hallo nochmal...

ich möchte auch dynamisch Module laden.
Dazu verwende ich eine Klasse die die ganze Sache automatisiert lädt.
Problem: Ich bekomme zwar keine Fehlermeldung, aber die Klassen werden nicht geladen.

So sieht die ganze Sache aus:

Code: Alles auswählen

class modules:
        """ class for importing the modules and get there outputs """

        def __init__(self, mods=[], txts='', bars=''):
                """ initialize all the things in modules """

                self.mods = str(readcfg('modules')).strip().split(sep)
                debug('Module: %s' % str(self.mods), 3, 'modules.__init__')
                self.mods = modules.modfunc(self)
                self.txts = modules.txtfunc(self)
                self.bars = modules.barfunc(self)



        def modfunc(self):
                x = []
                for mod in self.mods:
                        try:
                                exec "import %s" % mod
                                x.append(mod)
                        except:
                                raise
                                print "Can't load %s cause above error(s)." % mod

                rmods=[]
                for i in globals():
                        if i in self.mods:
                                rmods.append(i)

                debug("globals() sollte enthalten: %s" % str(self.mods), 3, 'modules.mods')
                debug("...und enthält davon: %s" % str(rmods), 3, 'modules.mods')

                return self.mods



        def txtfunc(self):
                x = []
                for mod in self.mods:
                        try:
                                #exec "x.append(%s.main()[0])" % mod
                                modobj = __import__(mod)
                                x.append(modobj.main()[0])
                        except:
                                raise
#                               print "Can't add text from %s cause above error(s)." % mod

                return x



        def barfunc(self):
                x = []
                for mod in self.mods:
                        try:
                                #exec "x.append(%s.main()[0])" % mod
                                modobj = __import__(mod)
                                x.append(modobj.main()[1])
                        except:
                                raise
#                               print "Can't add meter from %s cause above error(s)." % mod

                return x

ausgabe:

Code: Alles auswählen

Debug from modules.__init__: Module: ['battery', 'time']
Debug from modules.mods: globals() sollte enthalten: ['battery', 'time']
Debug from modules.mods: ...und enthält davon: []
Traceback (most recent call last):
  File "./szs.py", line 228, in ?
    init('all')
  File "./szs.py", line 187, in init
    modules()
  File "./szs.py", line 24, in __init__
    self.txts = modules.txts(self)
  File "./szs.py", line 55, in txts
    exec "x.append(%s.main()[0])" % mod
  File "<string>", line 1, in ?
NameError: name 'battery' is not defined

Verfasst: Freitag 22. Oktober 2004, 12:27
von Milan
Hi. Tut mir leid, aber deine Klasse sieht mir aus wie eine totale Fehlkonstruktion... In der Init überschreibst du Methoden durch Listen, sodass man schon beim lesen des Codes verwirrt wird. Dann verwendest du eine überflüssige try Klausel, da in der except Klausel (nicht näher definiert, was die überhaupt fangen soll) gleich eine raise Anweisung steht, die das try überflüssig macht. Das print wird in der except Klausel schon gar nicht mehr ausgeführt. Außerdem arbeitest du mit exec. Das bringt zum einen Unübersichtlichkeit und zum anderen Sicherheitslücken mit sich. Das ließe sich wunderbar umgehen:

Code: Alles auswählen

#exec "import %s" % mod
modulobj = __import__(mod)
#exec "x.append(%s.main()[0])" % mod
x.append(modulobj.main()[0])
Außerdem: was macht readcfg? Was beinhaltet sep? Ohne das kann man nicht schauen, was der Code macht und wo genau der Fehler liegt. Meiner Meinung nach verdiehnt die Klasse ein rewrite... :roll:

mfg Milan

Verfasst: Freitag 22. Oktober 2004, 14:17
von Milan
Hi. Ich hab mir den Code nochmal angeschaut... durch das für mich ungewohnte exec bin ich nicht gleich darauf gekommen. Wenn ich es richtig verstehe, wird in modules.mods (also der Methode und nicht der Liste :roll: ) das Modul battery importiert. Allerdings geschieht dies nur locals, nicht global. Damit das Modul dir dann auf global zur Verfügung stünde, müsstest du es mit global[/b[ als solches definieren. Sonst wird es nach der Ausführung der Methode nicht mehr gebraucht :wink: . Oder man müsste ganz tief in die Tricktasche greifen und in txts das benötigte Modul aus sys.modules rausfischen. Du musst also die Modulobjekte zwischenspeichern, sonst werden sie wieder gelöscht.

Verfasst: Freitag 22. Oktober 2004, 14:37
von pSy
habe den obigen Eintrag editiert... so sieht meine Klasse jetzt aus.

Und nun muss ich folgenden Bereich ändern?

Code: Alles auswählen

for mod in self.mods:
     try:
         exec "import %s" % mod
         x.append(mod)
     except:
Wie denn? Soetwas wie

Code: Alles auswählen

exec "global %s" % mod
darunter schreiben?

Jedenfalls scheint es irgendwie schon zu laufen. Weis aber noch nicht, ob es richtig läuft.
Bin erst Montag wieder da, danke für die schnelle Hilfe... :)

Verfasst: Freitag 22. Oktober 2004, 15:20
von Dookie
Hi,

ich würde auf das exec ganz verzichten.

Code: Alles auswählen

for mod in self.mods:
    x.append(__import__(mod, globals(), locals(), []))
return x
x enthält dann die Module


Gruß

Dookie

Verfasst: Montag 25. Oktober 2004, 12:02
von Gast
ah, dass sieht auch irgendwie sauberer aus als mein kleiner notfallbypass:

Code: Alles auswählen

globals().__setitem__(mod,locals().__getitem__(mod))
:D