Instanz importieren?

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
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Hallo!

Ich weiß nicht, ob ich nur einer Einbildung nachlaufe: Aber ist es eigentlich möglich, Instanzen zu importieren? Ich habe ein wunderbares Plugin-System und bin auch sehr zufrieden, finde es aber ziemlich lästig, dass jede Klasse immer einen Parameter "parent" braucht, über den ich die Instanz meiner Hauptklasse übergebe. Dieses Durchreichen der Objektreferenz (nocht der richtige Terminus?) ist doch völlig sinnfrei?!

Eigentlich müsste doch dadurch, dass ein Modul von meiner Hauptinstanz importiert wurde, irgendwie schon Zugriff darauf zu erlangen sein?

Um euch die Arbeit zu erleichtern hier ein Link auf ein "kaputtlachen"-Smiley :K

lG

Daniel
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Alles was du in einem Modul als globale Variable hast, kann du auch problemlos importieren.

Code: Alles auswählen

# foo.py
class Foo: pass
foo = Foo()
# bar.py
from foo import foo
print foo

jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Zu ersterem, ja (Darii war schneller).

Zu Deinem Plugin-System und dem parent kann ich nichts sagen, da ich nicht weiß, was Du damit meinst und wofür Du das parent nutzt. Plump gesprochen ist in Python jedes Modul ein Plugin. Und den parent-Parameter kenne ich von PyQt, da ist er allerdings nötig, um den Objektbaum intern mitzuführen. (Die PyQt-Klassen sind als C++Abkömmlinge sehr verschieden von Pythonklassen.)
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Gut, klar - damit kann ich die Klassen importieren. Das ist ja klar. Aber ich meine die Instanzen - also die bereits initialisierten Klassen, die einmalig sind und spezifische Eigenschaften haben.

lG

Daniel
BlackJack

@Barabbas: Genau das macht Darii doch -- es wird nicht die Klasse `Foo` importiert, sondern ein Exemplar davon: `foo`.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich glaube er meint Fälle, in denen Klassen von anderen (Python-)Programmen instanziert wurden. Dann wurden irgendwelche Funktionen aufgerufen, die bestimmte Eigenschaften der Klasse verändert haben und diesen Zustand will er nun importieren. Z.B. ``mechanize`` hat sich irgendwo eingeloggt und man will später nochmal auf diesen Zustand zurückgreifen. Ich würde da [mod]pickle[/mod] empfehlen. Allerdings muss das andere Programm die Klasse natürlich auch vorher picklen. Wenn du da keinen Einfluss drauf hast, ist schlecht.
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

ok, wahrscheinlich habe ich das Ganze nicht genau genug geschildert:

Ich habe mein Programm, das diesen "Objektbaum" hat (Bild).
Wenn ich nun dieses Programm ausführe, werden die gesamten Klassen initialisiert - dabei wird jeweils eine Referenz auf die nächsthöhere Instanz übergeben. D.h. clMain.main() bekommt eine Referenz auf clWindow.gtkWin() und alle Klassen die von clMain.main() initialisiert werden, bekommen eine Referenz auf clMain.main() übergeben.

Die Klasse clMain.main() sieht dann irgendwann grob so aus:

Code: Alles auswählen

class main():
    def __init__(self, parent):
        self.parent = parent
        self.DB = clDB.DB(self)
        self.plugins = clPlugins.Plugins(self)
Ich denke, das ist soweit nicht unüblich (wenn auch wahrscheinlich nicht besonders schön umgesetzt).

Nun ist doch aber klar, dass es für mich völlig unsinnig wäre, von der Klasse clPlugins.Plugin() aus die Klasse main() zu initialisieren - dann hätte ich ja zwei Instanzen meines Programmes laufen (und eine unendliche Schleife :]). Gleiches Problem bei den Plugins: Die sollen ja irgendwie auf mein Fenster zugreifen können, um etwa ein MenuItem hinzu zu fügen.

Und meine Frage ist lediglich: Muss ich an z.B. mein Plugin zwingend eine Referenz auf meine main() Klasse übergeben, um auf diese zuzugreifen zu können, oder gibt es eine Möglichkeit, diese bestehende (!) Instanz meiner Hauptklasse zu "importieren". Da das Plugin ja indirekt durch meine Hauptklasse importiert wurde, dachte ich, es gäbe vielleicht eine Möglichkeit, diese aufrufende Hauptklasse auch anzusprechen.

Das Beispiel von Darii macht ja nichts anderes, als eine Instanz einer Klasse zu erstellen. Das Erstellen wurde lediglich in ein anderes Modul ausgelagert.

Schöne Grüße,

Daniel[/code]
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Ok, jetzt ist klarer, wo die Reise hingehen soll. Du suchst quasi einen eleganten "Callback-Mechanismus", um von den Plugins auf die Gui zuzugreifen. Um das beantworten zu können, mußt Du ein paar Designfragen klären, auf die Schnelle fällt mir ein:
- multithreaded?
- MVC?
- Pluginresolver- und dispatcher?
- Interfaces?
- Plugintypen? Z.B. sind Plugins von Gui-Klassen abgeleitet und bringen daher Signaltechniken mit usw.

<klugscheiß>Die Designüberlegungen sind für Dich von zentraler Wichtigkeit, um nicht bei einem Anti-Pattern zu landen.</klugscheiß>
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

jerch hat geschrieben:Ok, jetzt ist klarer, wo die Reise hingehen soll. Du suchst quasi einen eleganten "Callback-Mechanismus", um von den Plugins auf die Gui zuzugreifen. Um das beantworten zu können, mußt Du ein paar Designfragen klären, auf die Schnelle fällt mir ein:
Ja, und nicht nur auf die GUI sondern auf den ganzen Objektbaum. Die Plugins müssen natürlich auch auf die offen Datenbankverbindung zugreifen können und verschiedene Attribute lesen / setzen können.

Zu deinen Fragen:

Threading: Ich benutze kein GTK Threading sondern habe nur ab und an Funktionen, die bestimmte Daten über einen Thread aus dem Internet ziehen.

MVC: Keine Ahnung was das ist. Bei meiner Google-Suche stieß ich auf "pydispatcher", der sowas machen soll. Ich habe eine eigene Implementierung für Events und keinerlei Dispatcher (was immer das ist).

Pluginresolver- und dispatcher: Sagt mir leider auch wenig. Ich nutze ein eigenes Plugin-System - die einzelnen Plugins werden via Textfile "angemeldet" und müssen ein Verzeichnis sein, das eine Datei "__init__.py" mit einer darin enthaltenen Klasse "main" enthält. Diese Klasse wird dann für jedes Plugin instanziiert und in den Objektbaum eingebunden.
Leider (?) leite ich die Plugins von keinerlei Klasse ab - das kann man bisher halten wie man will.

Nach Lektüre des Wiki-Artikels zum Thema Anti-Pattern (sehr bereichernd), bezichtige ich mich also zumindest, das quadratische Rad neu erfunden zu haben.
Bisher hat sich mein Modell eigentlich als erstaunlich flexibel erwiesen. Da ich - wie du merkst - natürlich kein Profi bin, wäre es zu verkraften, wenn ich hier mal an die Grenzen meines Konzeptes stoße.
BlackJack

@Barabbas: Das klingt für mich fast so als wenn Du gerne programmglobale Variablen haben möchtest. Nicht gut.

Warum willst Du das `parent` denn nicht übergeben, sondern irgendwie mit "Magie" da dran kommen? Das ist so die direkteste, sauberste, und auch recht flexible Art.
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Naja, kurz gesagt: Ich meine *irgendwie* mal gehört / gesehen zu haben, dass soetwas geht. Und da dachte ich mir, es sei sehr viel schöner, das entsprechende Objekt zu "importieren" als die Referenz darauf über verschiedene Instanzen hinweg durch zu reichen.

Ich kann nicht behaupten, dass ich jetzt ein Problem hätte, das sich sonst nicht lösen ließe - ich dachte nur, dass es vielleicht eine bessere Methode gäbe.
Oder anders: Ich wollte meine Plugin-Schnittstelle ausmisten.

Danke aber für eure Hinweise! Ich werde wahrscheinlich wirklich erstmal bei dem bestehenden System bleiben, jerchs "Frageliste" lässt mich erahnen, dass das, was ich mir ausgemalt habe, nicht gerade trivial ist.

lG

brb
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Ich habe mir mal den Dateibaum Deines Projektes angeschaut. Ich finde die Plugin-Lastigkeit übertrieben (ein Audioplayer im Komponentenmodellstil). Dieses Designkonzept verschließt sich mir bei einem solchen in einer Skriptsprache geschriebenem Projekt.

Sind die Plugins überhaupt noch "echte" Plugins, d.h. funktioniert die Anwendung noch ohne diese? In jedem Falle solltest Du aufpassen, das die Funktionalitäten gut geschachelt sind und nicht jedes Plugins sonst welche "framework"-weiten Datentypen manipulieren kann. Auch das die meisten Plugins nur noch in den __init__.py-Dateien leben, erhöht nicht gerade die Wartbarkeit.

Für die Kommunikation innerhalb Deines Audioplayerframeworks könntest Du Dir mal Observer/Listener/Mediatormuster zu Gemüte führen. Die Kanone, mit der Du hier schießt, wird damit allerdings definitiv nicht kleiner ;)
Für den Anfang ist eine Referenzmitführung via parent brauchbar und weniger fehlerträchtig, kompliziert wirds, wenn die Komponenten untereinander reden können sollen.
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Danke für deine Mühe!

Ich habe mich für Verzeichnis-Module entschieden, um die Übersicht im plugin-Verzeichnis zu wahren. Natürlich sind die meisten Module sehr einfach, weshalb mehr als die obligatorische __init__.py nicht nötig ist. Ich glaube aber, dass das ein kleineres Problem ist.

Und ja, Pyjama läuft prima ohne Plugins. Ich auch achte sehr darauf, dass ich nicht lauter sich gegenseitig bedingende Plugins habe. Tatsächlich ist es so, dass die verschiedenen Plugins meist ohne Anpassungen mit den vorhandenen Schnittstellen arbeiten - ich habe das immer als Zeichen für ein gutes Design aufgefasst ;).
Von einer Ausnahme abgesehen sind die meisten meiner Erweiterungen eben genau das: sie fügen Funktionen hinzu, die für das Programm nicht obligatorisch sind und die man ggf. deaktivieren kann. Ich fand, dass das das Programm eher übersichtlicher macht.

Wie auch immer, ich werde mich mal informieren, was es mit dem Observer/Listener Modell auf sich hat.

Danke nochmal,

Daniel
Antworten