Seite 1 von 1

Probleme mit Pluging-Framwork und globalen import

Verfasst: Samstag 4. Mai 2013, 13:02
von av_jui
Hallo

Ich bin noch total unerfahren was Python angeht, jedoch wollte ich mich jetzt mal ein Projekt wagen, dass auch ein Pluginsystem bietet.
Leider stoße ich momentan an eine Grenze die ich alleine wohl nicht hin bekomme.
Und zwar geht es darum diese Plugins zu laden und die Module zu importieren. Ich habe jetzt schon einiges durchprobiert aber irgendwie komm ich nicht weiter.
Ich hab hier mal die https://github.com/avjui/Homepy/blob/pl ... Manager.py.
Ich hab auch mal zum testen ein

Code: Alles auswählen

sys.modules.keys()
eingebaut um zu sehen welche Module geladen werden.

Hier sehe ich dann auch das was importiert wurde (webcams,homematic,sonos) aber wenn ich das dann aufrufe bekomme ich immer
folgenden Fehler.

Code: Alles auswählen

Traceback (most recent call last):
  File "Homepy.py", line 128, in <module>
    main()
  File "Homepy.py", line 113, in main
    homematic.client().get_name()
NameError: global name 'homematic' is not defined
Kann mir bitte jemand helfen?

P.S. Python ist 2.7 falls das wichtig ist

Re: Probleme mit Pluging-Framwork und globalen import

Verfasst: Samstag 4. Mai 2013, 13:35
von BlackJack
@av_jui: Es gibt keinen globalen Import. Du hast den Namen `homematic` an nichts gebunden, also ist der auch nicht bekannt. Die `get_plugins()`-Methode gibt die Plugins zurück, Du machst mit dem Rückgabewert aber überhaupt nichts.

Edit: Namen mit einem führenden Unterstrich bedeuten, dass das Implementierungsdetails sind, die man von aussen nicht verwenden sollte. Das betrifft `_load_all()`, aber insbesondere `os._exit()`. Davon solltest Du auf jeden Fall die Finger lassen! Was gefällt Dir an dem öffentlichen `sys.exit()` nicht?

Re: Probleme mit Pluging-Framwork und globalen import

Verfasst: Samstag 4. Mai 2013, 14:48
von Sirius3
@av_jui: ich sehe Du hast im Vergleich zum Original in Deinem »PluginManager« einiges verschlimmbessert:
- Wenn »x« schon mit .py endet dann kann es nie mit .pyc enden (Ein Generatorausdruck wäre hier passender als extra eine neue Liste zu erzeugen).
- Da bei »mod« die Endung .py entfernt wurde, wird der Vergleich mit '__init__.py' immer fehlschlagen.
- sys.path.insert und del sollten zusammenpassen.

Ich will jetzt nichts falsches sagen, aber ein mit _ beginnender Klassenname außerhalb des Moduls benutzen zu müssen, ist für mich seltsam. Wahrscheinlich soll der _ andeutet, dass es sich um eine abstrakte Klasse handelt, ich persönlich würde das eher mit »AbstractPlugin« kennzeichnen.

Re: Probleme mit Pluging-Framwork und globalen import

Verfasst: Samstag 4. Mai 2013, 19:40
von av_jui
BlackJack hat geschrieben:@av_jui: Es gibt keinen globalen Import. Du hast den Namen `homematic` an nichts gebunden, also ist der auch nicht bekannt. Die `get_plugins()`-Methode gibt die Plugins zurück, Du machst mit dem Rückgabewert aber überhaupt nichts.
Und was heißt das jetzt? Beim get_plugins wird ja auch _load_all aufgerufen und da wird ja das Modul importiert. Oder versteh ich das Falsch? Wie kann ich diese Funktionen den nutzen.
BlackJack hat geschrieben:Edit: Namen mit einem führenden Unterstrich bedeuten, dass das Implementierungsdetails sind, die man von aussen nicht verwenden sollte. Das betrifft `_load_all()`, aber insbesondere `os._exit()`. Davon solltest Du auf jeden Fall die Finger lassen! Was gefällt Dir an dem öffentlichen `sys.exit()` nicht?
Ist mir klar war auch nur zum Testen. danach nehme ich get_plugins(). Zum sys.exit hast natürlich recht ist auch ein Überbleibsel von einem Versuch. Ich sollte mal den Code aufräumen :roll:
Sirius3 hat geschrieben: - Da bei »mod« die Endung .py entfernt wurde, wird der Vergleich mit '__init__.py' immer fehlschlagen.
- sys.path.insert und del sollten zusammenpassen.
Ich weiß habe ich hier schon geändert kam vom spielen aus Verzweiflung.

Re: Probleme mit Pluging-Framwork und globalen import

Verfasst: Samstag 4. Mai 2013, 19:48
von BlackJack
@av_jui: Das heisst jetzt das die Module von der Methode *zurückgegeben* werden. Schau Dir doch einfach mal an was Du dort bekommst.

Re: Probleme mit Pluging-Framwork und globalen import

Verfasst: Samstag 4. Mai 2013, 19:55
von av_jui
BlackJack hat geschrieben:@av_jui: Das heisst jetzt das die Module von der Methode *zurückgegeben* werden. Schau Dir doch einfach mal an was Du dort bekommst.
Zurück liefert es

Code: Alles auswählen

{'Cams': <class 'webcams.cam'>, 'Test': <class 'sonos.Sonos'>, 'Homematic': <class 'homematic.client'>}
Und was heißt das für mich, wenn ich jetzt das homematic.client nutzen möchte?

Re: Probleme mit Pluging-Framwork und globalen import

Verfasst: Samstag 4. Mai 2013, 20:00
von BlackJack
@av_jui: Ist die Frage ernst gemeint? Das sieht sehr nach einem Wörterbuch (`dict()`) aus. Und Zeichenketten als Schlüsseln. Und zu dem Schlüssel 'Homematic' gibt es einen Wert der augenscheinlich die Klasse `homematic.client` ist. Hol den Wert da raus und mach damit was Du damit machen willst.

Re: Probleme mit Pluging-Framwork und globalen import

Verfasst: Samstag 4. Mai 2013, 20:06
von av_jui
BlackJack hat geschrieben:@av_jui: Ist die Frage ernst gemeint? Das sieht sehr nach einem Wörterbuch (`dict()`) aus. Und Zeichenketten als Schlüsseln. Und zu dem Schlüssel 'Homematic' gibt es einen Wert der augenscheinlich die Klasse `homematic.client` ist. Hol den Wert da raus und mach damit was Du damit machen willst.
Das das ein dict ist ist schon klar, aber mir ist nicht klar wie ich jetzt das homematic.client verwenden kann. Muß ich das hier nochmal importiern (__import__)? was bringt dann das __import__ in der _load_all Funktion? Ich kapiere es einfach nicht.

Edit: Gibt es auch ein fertiges python Plugin Framework was ich nehmen könnte

Re: Probleme mit Pluging-Framwork und globalen import

Verfasst: Samstag 4. Mai 2013, 20:20
von BlackJack
@av_jui: Nochmal: Du holst das Objekt da einfach heraus und *verwendest* es.

Code: Alles auswählen

plugins = pluginmgr.get_plugins()
client_class = plugins['Homematic']
client = client_class()
print client.get_name()
# 
# oder:
# 
print pluginmgr.get_plugins()['Homematic']().get_name()
Oder halt irgend etwas sinnvolles zwischen diesen beiden Extremen.

Re: Probleme mit Pluging-Framwork und globalen import

Verfasst: Samstag 4. Mai 2013, 20:30
von av_jui
BlackJack hat geschrieben:@av_jui: Nochmal: Du holst das Objekt da einfach heraus und *verwendest* es.

Code: Alles auswählen

plugins = pluginmgr.get_plugins()
client_class = plugins['Homematic']
client = client_class()
print client.get_name()
# 
# oder:
# 
print pluginmgr.get_plugins()['Homematic']().get_name()
Oder halt irgend etwas sinnvolles zwischen diesen beiden Extremen.
Das heißt das sind immer subclasses von pluginmgr.get_plugins()? Verstehe ich das jetzt richtig?

Re: Probleme mit Pluging-Framwork und globalen import

Verfasst: Samstag 4. Mai 2013, 21:05
von cofi
Nein, das verstehst du falsch.

`get_plugin()` liefert ein Dictionary mit Strings als Schluesseln und Klassen als Werten. Unterklassen oder Vererbung im Allgemeinen hat damit gar nichts zu tun.

Code: Alles auswählen

client = pluginmgr.get_plugins()['Homematic']
ist hier dann aequivalent zu

Code: Alles auswählen

from homematic import client
wenn `homematic` ein normales Modul ist.

Re: Probleme mit Pluging-Framwork und globalen import

Verfasst: Samstag 4. Mai 2013, 22:57
von av_jui
Danke für die Antworten. Ich denke ich kapier es jetzt einigermaßen.

Re: Probleme mit Pluging-Framwork und globalen import

Verfasst: Montag 11. November 2013, 20:46
von av_jui
Hallo

Ich mal wieder. Nach langer Zeit habe ich mal wieder weitergemacht.
Und siehe da, ich hab wieder mal ein Problem mit meinem Plugin-Framework.
Ich hätte gerne das nur nach Plugins in Verzeichnissen mit einer Tiefe von 1 gesucht wird.
Hier mal die relevante Stelle im Code.

Code: Alles auswählen

    def __init__(self):

        self.plugin_dirs.update({
                                 'plugins/homeautomation/' : False,
                                 'plugins/multimedia/' : False,
                                 'plugins/notification' : False,
                                 'plugins/web/' : False,
                                 })

    def _load_all(self):
        for (pdir, loaded) in self.plugin_dirs.iteritems():
            if loaded: continue

            for root,dirs,mod in os.walk(pdir):
                sys.path.insert(0, root)            
                for mod in [x[:-3] for x in os.listdir(root) if x.endswith('.py')]:
                    if mod and mod != '__init__':
                        if mod in sys.modules:
                            log('Module %s already exists, skip' % mod, 'info')
                        else:
                            try:
                                pymod = __import__(mod)
                                splitted = mod.split('.')
                                self.plugin_dirs[pdir] = True
                                log("Plugin Found [Name] %s	[Path] %s"% (mod, pymod.__file__), 'info')
                                self.plugins = DBFunction().GetList('plugins')
                                for p in self.plugins:
                                     if p[1] == mod.upper():
                                        self.adding = False
                                        break
                                     else:
                                       self.adding = True

                                if self.adding:
                                     DBFunction().AddPlugin(mod.upper(), pymod.__file__.split('/')[1])
                            except ImportError, e:
                                log ('Loading failed, skip plugin %s/%s' % (os.path.basename(root), mod), 'error')

                del(sys.path[0])
Bei Zeile 14 starte ich ein os.walk.
z.b für 'plugins/homeautomation/' gibt dirs folgendes aus.

Code: Alles auswählen

['dmx', 'loewe']
Hier möchte ich nur um 1 höher in die Verzeichnisse. Und dann sollte er mit dem nächsten "Typ" plugin weitermachen.
Hintergrund ist das so das Plugin selber Module mitbringen kann ohne das diese dann auch als Plugin angesehen werden.
Ein Codevorschlag wäre echt toll.

Danke im Voraus

Re: Probleme mit Pluging-Framwork und globalen import

Verfasst: Dienstag 12. November 2013, 11:28
von av_jui
Niemand ne Idee?

Re: Probleme mit Pluging-Framwork und globalen import

Verfasst: Dienstag 12. November 2013, 12:00
von EyDu
Wenn du nur eine Suchtiefe von 1 haben willst, dann solltest du besser nicht ``os.walk`` verwenden. Benutze besser ``os.listdir``, dann gibt es auch keine Sonderfälle mehr mit Modulen in Plugins.

Re: Probleme mit Pluging-Framwork und globalen import

Verfasst: Dienstag 12. November 2013, 23:01
von av_jui
Danke werde ich mal versuchen. Wobei ich mittlerweile eine Lösung gefunden habe.