Module dynamisch einbinden

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
Eleetchen
User
Beiträge: 2
Registriert: Sonntag 10. Oktober 2004, 15:55

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
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Hi!

Code: Alles auswählen

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

Gruß, mawe
Vortec
User
Beiträge: 52
Registriert: Dienstag 10. Dezember 2002, 11:54

Befass dich mal mit der Funktion "reload", oder schau dir den Code von meinem Bot an, der genau das macht. (-> Signatur)
| [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] |
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Hi!

Ob reload() wirklich das richtige ist? In der Doku steht
... The module must have been successfully imported before.
Gruß, mawe
Vortec
User
Beiträge: 52
Registriert: Dienstag 10. Dezember 2002, 11:54

Ansonsten auch gerne imp.
This module provides an interface to the mechanisms used to implement the import statement.
| [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] |
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hi,

na wenn schon __import__


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Eleetchen
User
Beiträge: 2
Registriert: Sonntag 10. Oktober 2004, 15:55

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
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

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.
pSy
User
Beiträge: 44
Registriert: Montag 4. Oktober 2004, 17:58
Kontaktdaten:

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
Zuletzt geändert von pSy am Freitag 22. Oktober 2004, 14:33, insgesamt 1-mal geändert.
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

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
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

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.
pSy
User
Beiträge: 44
Registriert: Montag 4. Oktober 2004, 17:58
Kontaktdaten:

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... :)
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

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
[code]#!/usr/bin/env python
import this[/code]
Gast

ah, dass sieht auch irgendwie sauberer aus als mein kleiner notfallbypass:

Code: Alles auswählen

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