nutzen von erst zur laufzeit bekannten klassen und methoden

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
Benutzeravatar
dall♀
User
Beiträge: 12
Registriert: Dienstag 23. März 2010, 15:44

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!
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.
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.
Benutzeravatar
dall♀
User
Beiträge: 12
Registriert: Dienstag 23. März 2010, 15:44

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! :)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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 ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten