Seite 1 von 1

nutzen von erst zur laufzeit bekannten klassen und methoden

Verfasst: Montag 28. November 2011, 15:53
von dall♀
guten tag liebe forumsgemeinde,

ich schreibe momentan (seit gefühlten jahren) in python eine GUI für ein messgerät (unter ubuntu). mit den gelesenen messdaten sollen während der messung auch berechnungen angestellt werden können (z.b. mittelwert eines messkanals oder aktueller mittelwert über alle messkanäle usw.).

dazu hab ich mir folgendes ausgedacht:
der nutzer soll eigenhändig skripte in das unterverzeichnis "modules/calc" meines arbeitsverzeichnisses ablegen können, die jeweils eine klasse enthalten, die von meiner basisklasse "Calculation" erbt. in der basisklasse sind konstruktor und destruktor implementiert, die dafür sorgen, dass jedes erstellte element eine einzigartige ID bekommt. die unterklassen implementieren nur die methode "calc".

in der gui soll der benutzer aufgelistet bekommen, welche unterklassen (also berechnungsmethoden) verfügbar sind und diese auch wählen und benutzen können. wie schaffe ich es jetzt, ohne zu wissen, wie diese unterklassen genau heißen, sie zur laufzeit ins programm zu laden und zu benutzen?

hab schon mit globals() experimentiert in der form (className ist in dem fall gleichzeitig der dateiname der unterklasse, so komme ich an ihn ran):

Code: Alles auswählen

calcClass = globals()[className]
instance = calcClass()
das funktioniert nicht, weil die benutzerdefinierten skripte noch nicht importiert worden und in globals() nicht enthalten sind.

andere versuche waren, alle calc-Funktionen in eine Klasse zu tun und diese dann mit

Code: Alles auswählen

Calculation.__dict__
abzuholen.. ist mir aber nicht so lieb, weil ich jede berechnung in einer eigenen datei haben möchte.

was sind eure ideen dazu? wie kann man das problem (besser) lösen? es ist vor allem wichtig, dass die berechnungs-skripte von nutzer zu nutzer austauschbar sind.
vielen dank im voraus für die antworten!

Re: nutzen von erst zur laufzeit bekannten klassen und metho

Verfasst: Montag 28. November 2011, 16:05
von deets
Das, was du suchst, wird ueblicherweise ein Plugin-System genannt. Und wenn du unter dem Stichwort hier oder bei google suchst, wirst du eine Vielzahl von Loesungen finden, mit verschiedenen Schwerpunkten.

Re: nutzen von erst zur laufzeit bekannten klassen und metho

Verfasst: Montag 28. November 2011, 21:45
von BlackJack
@dall♀: "Destruktor" klingt gefährlich. Falls Du tatsächlich `__del__()` implementiert hast, solltest Du die Dokumentation dazu noch einmal genau durchlesen. Insbesondere die Warnungen. Es ist nicht garantiert wann die Methode aufgerufen wird, nicht einmal *ob* sie überhaupt aufgerufen wird, und ihre blosse Existenz kann unter Umständen zu Speicherlecks führen.

`Calculation` mit einer Methode `calc()` klingt ausserdem stark nach Java. Wenn so ein Objekt tatsächlich nur eine Funktion darstellen soll, würde ich das auch mit Funktionen machen. Beziehungsweise allgemeiner mit aufrufbaren Objekten. Man könnte zum Beispiel die Plugin-Programmierer ihre Funktionen selbst explizit registrieren lassen. Gerne auch mit einem zur Verfügung gestellten Decorator.

Re: nutzen von erst zur laufzeit bekannten klassen und metho

Verfasst: Montag 12. Dezember 2011, 12:01
von dall♀
hab unter dem stichwort "plugin-system" gesucht und bin fündig geworden.. da gibt es ja wirklich eine fülle von möglichkeiten!
hab mich für das nutzen von imp entschieden:

Code: Alles auswählen

import imp, os
# className ist der name der vom benutzer gewählten berechnungsfunktion
impData = imp.find_module(className, [os.getcwd() + '/modules/calc/'])
calcClasses[className] = getattr(imp.load_module(className, impData[0], impData[1], impData[2]), className)
# so habe ich dann alle klassen im dictionary self.__calcClasses gespeichert. instanzen der klassen kann ich dann so erstellen:
calc1 = calcClasses[className]()
und wegen des destruktors.. der rat wird beherzigt, vielen dank! :)

Re: nutzen von erst zur laufzeit bekannten klassen und metho

Verfasst: Montag 12. Dezember 2011, 12:37
von Hyperion
Für das Zusammensetzen von Pfaden solltest Du Dir mal ``os.path.join`` angucken. Und ob ``os.getcwd()`` hier wirklich eine gute Idee ist... denk mal drüber nach ;-)