Konstruktoren und Objekte in andern Klassen

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
sandra84
User
Beiträge: 17
Registriert: Mittwoch 9. Juni 2010, 06:34

Holla,

ich hätte mal eine Verständnissfrage, weil ich bin beim rumprobieren auf ein etwas, für mich, eigenartiges Verhalten gestossen.

Und zwar ich habe zwei Klassen und erzeuge in der __init__ von der einen Klasse ein Object der anderen
sprich

Klasse eins
__init__
ObjektZwei = zwei()
Funktion
ObjektZwei.Funktion2()

Klasse zwei
__init__
self.Variable = Funktion(z)

Funktion (self, z)
mach was mit z
return z
Funktion 2
mach was, wo self.Variable unbedingt gebraucht wird

Sooooo ich hatte vorhin ein Konstrukt, wo es ihn damit hingehauen hat. Und zwar wurde Funktion aus Klasse zwei wohl einmal aufgerufen, aber wenn ich danach in einer Funktion von Klasse eins was mit anstellen wollte, dann ging das nicht
Bei mir kam dann son Broken Pipe Error o.s.ä.

Wenn ich aber die Funktion (Klasse 2) in Funktion 2 aufgerufen hab, dann gings ohne Probleme

Ich hab da so ein Verständnisproblem, warum das so ist, da ich im Konstruktor von Klasse Eins ja ein Objekt von Klasse Zwei erzeugt habe. Damit müsste ja der Konstruktor aufgerufen worden sein und wenn ich dann die Funktionen des Objekts aufrufe müsste das doch gehen. Oder macht Python das anders?
BlackJack

@sandra84: Sorry, aber bei einer so allgemeinen Beschreibung und einem so speziellen Fehler kann man ja nicht einmal vernünftig raten wo das Problem gelegen haben mag.
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Vielleicht kannst du ein minimales lauffähiges Beispiel einstellen, dann können wir dir sicher besser helfen.
sandra84
User
Beiträge: 17
Registriert: Mittwoch 9. Juni 2010, 06:34

*lach* würd ich gerne unglücklicherweise krieg ichs nich hin, dass es nich mehr funktioniert :P
sandra84
User
Beiträge: 17
Registriert: Mittwoch 9. Juni 2010, 06:34

aber weil wir mal gerade dabei sind..

ich bin jetzt auch schon wo anders beim einarbeiten und zwar

habe ich n paar Knöpfchen der einen Input-Dialog aufruft.
Soweit so gut.

self.connect(self.UI.Knopf1, QTCore.SIGNAL("clicked()"), self.showDialog)
self.connect(self.UI.Knopf2, QTCore.SIGNAL("clicked()"), self.showDialog)
self.connect(self.UI.Knopf3, QTCore.SIGNAL("clicked()"), self.showDialog)

Jetzt hab ich das Problem, dass ich in der showDialog ja gar nicht weiss welcher Knopf gedrückt wurde..
Kennt da jmd ne Möglichkeit?

So ein Konstrukt schluckt er ja nicht (und fänd ich auch nicht so schön)

self.connect(self.UI.Knopf1, QTCore.SIGNAL("clicked()"), self.showDialog(self.Knopf1))

Achso und vergessen.. wie komm ich an den rückgabewert von showDialog ran? Denn es kann ja durchaus mal vorkommen dass ein Button irgendeine Funktion auslöst, deren Rückgabewert irgendwie noch weiterverarbeitet werden muss.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

sandra84 hat geschrieben:So ein Konstrukt schluckt er ja nicht (und fänd ich auch nicht so schön)

self.connect(self.UI.Knopf1, QTCore.SIGNAL("clicked()"), self.showDialog(self.Knopf1))
Nein, aber er schluckt z.B `lambda: self.showDialog(self.Knopf1)` oder `functools.partial(self.showDialog, self.Knopf1)` allerdings muss dann `self.showDialog` auch ein Argument uebernehmen koennen.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

sandra84 hat geschrieben:self.connect(self.UI.Knopf1, QTCore.SIGNAL("clicked()"), self.showDialog(self.Knopf1))
Sollte das ein Beitrag für das Qt/KDE-Forum werden? Es ist für mich etwas frustrierend hier im allgemeinen Forum die Beiträge zu lesen um dann zu merken, dass das gar kein Thema ist mit dem ich mich auskennen könnte und dass es eigentlich woanders hin gehört.

Bitte verwende
1. das passende Forum
2. python Code-Tags in deinen Beiträgen
sandra84
User
Beiträge: 17
Registriert: Mittwoch 9. Juni 2010, 06:34

Kloar die erste frage bleibt ja weiterhin bestehen :P
wollt nur nich 1000000000 postings aufmachen

sry

Aso und ja geht! :P
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

sandra84 hat geschrieben:Jetzt hab ich das Problem, dass ich in der showDialog ja gar nicht weiss welcher Knopf gedrückt wurde..
Kennt da jmd ne Möglichkeit?
Ja, verschiedene Aufgaben, verschiedene Methoden:

Code: Alles auswählen

self.connect(self.UI.Knopf1, QTCore.SIGNAL("clicked()"), self.showDialog1)
self.connect(self.UI.Knopf2, QTCore.SIGNAL("clicked()"), self.showDialog2)
self.connect(self.UI.Knopf3, QTCore.SIGNAL("clicked()"), self.showDialog3)
Gib den Methoden aber bitte sinnvollere Namen.
sandra84 hat geschrieben:Kloar die erste frage bleibt ja weiterhin bestehen :P
So lange du da nicht mit mehr Informationen rüberrückst und deinen Code endlich mal on Code-Tags setzt wird dir das keiner beantworten können.
sandra84
User
Beiträge: 17
Registriert: Mittwoch 9. Juni 2010, 06:34

ich sag doch ich hab den Code nimmer.. bzw. nicht mehr so dass er nicht mehr funktioniert. Wenn ich wieder ma drauf stosse, dann werd ich dies tun.. Trotzdem versteh ich die Forderung danach nicht. Ich habe niemals um die Lösung des Problems gebeten, deshalb sollte Pseudocode vollkommen ausreichen.

Da gibts keine verschiedenen Aufgaben.. der Dialog macht genau immer das gleiche und ich werde mich hüten da 10x die gleiche Methode zu schreiben..

das mit der lambda-Funktion funktioniert einwandfrei.
ichisich
User
Beiträge: 134
Registriert: Freitag 1. Januar 2010, 11:52

Code: Alles auswählen

Klasse eins
__init__
ObjektZwei = zwei()
Funktion
ObjektZwei.Funktion2()

Du hast dazu geschrieben:

Und zwar wurde Funktion aus Klasse zwei wohl einmal aufgerufen, aber wenn ich danach in einer Funktion von Klasse eins was mit anstellen wollte, dann ging das nicht
Wenn Du das tasächlich so machst (gemacht hast) fehlt da meines Erachtens das self vor dem "ObjektZwei" um ein Klassenmember zu erhalten. Andernfalls ist das Objekt nur lokal in der __ini__ methode sichtbar.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

ichisich hat geschrieben:Wenn Du das tasächlich so machst (gemacht hast) fehlt da meines Erachtens das self vor dem "ObjektZwei" um ein Klassenmember zu erhalten. Andernfalls ist das Objekt nur lokal in der __ini__ methode sichtbar.
Instanzattribut, Klassenattribute werden nicht an die Instanz und damit nicht an `self` gebunden.
ichisich
User
Beiträge: 134
Registriert: Freitag 1. Januar 2010, 11:52

Also damit ich es auch kapier:
Hier meine Interpretation das pseudozeugs:

Code: Alles auswählen

class Eins(object):
	def __init__(self):
		print "__init__ Eins"
		zwei = Zwei()
	
	def funktion1(self):
		zwei.funktion2(10)

class Zwei(object):
	def __init__(self):
		print "__init__ Zwei"
	
	def funktion2(self, intTest):
		print "funktion2:", intTest

if __name__ == "__main__":
	print "Hallo Main"
	eins = Eins()
	eins.funktion1()
Wirft zwar keinen
son Broken Pipe Error o.s.ä.
aber auf alle Fälle einen:

Code: Alles auswählen

    zwei.funktion2(10)
NameError: global name 'zwei' is not defined
Ein "self." vor die zwei zweis machts dann lauffähig.
Spricht man da nicht von Sichtbarkeit des/der Klassenmebers/Instanzvariablen da der name "zwei" danach global definiert ist?

PS.
(Klassenmember war so gesehen falsch da es sich ja um ein(e) Instanzvariablen/Instanzattribut handelt)
sandra84
User
Beiträge: 17
Registriert: Mittwoch 9. Juni 2010, 06:34

Ja.. ne also ja.. wenn die meldung gekommen wäre wäre ich auch auf die idee gekommen n self davor zu schreiben ;P

Ne ich versuchs ma zu rekonstruieren.. wenn ich zeit hab
sandra84
User
Beiträge: 17
Registriert: Mittwoch 9. Juni 2010, 06:34

So jetzt gehts wieder nimmer

Und zwar:

Code: Alles auswählen


class Machs():
    def __init__(self):
        Path="./test.out"
        self.client = subprocess.Popen(clientPath,
          shell=True,
          stdout=subprocess.PIPE,
          stdin=subprocess.PIPE)
        if not os.path.exists(Path):
            print "Ups, Programm net da ", Path
            sys.exit()

    def sendCommand(self, cmd):
        Path="./test.out"
        self.client = subprocess.Popen(clientPath,
          shell=True,
          stdout=subprocess.PIPE,
          stdin=subprocess.PIPE)
        if not os.path.exists(Path):
            print "Ups, Programm net da ", Path
            sys.exit()
    
        self.client.stdin.write(cmd +"\n")
        self.client.stdin.flush()
        line =  self.client.stdout.readline().rstrip()
        self.client.stdout.flush()
        return line

class MyGuiClass(QtGui.QMainWindow):
    def __init__(self, uiRef):
        QtGui.QMainWindow.__init__(self)
        self.uiRef = uiRef
        uiRef.setupUi(self)
        self.ctimer = QtCore.QTimer()
        self.worker =Machs()
        self.connect(self.uiRef.BUTTON_AV42_M2ESG01_AV042__SFEN__F2, QtCore.SIGNAL("clicked()"), lambda:self.showDialog('AV42_M2ESG01_AV031_SFEN_F2'))

    def showDialog(self, ButtonName):
        text, ok= QtGui.QInputDialog.getText(self, 'Enter Signal', ButtonName)
        if ok:
            self.worker.sendCommand('write '+text)
            print ButtonName, "send: ",  unicode(text)

Bei der vorletzten Zeile haut er mir dann
"IOError:[Errno 32] Broken pipe raus

Wenn ich aber die showDialog umbaue

Code: Alles auswählen

    def showDialog(self, ButtonName):
        text, ok= QtGui.QInputDialog.getText(self, 'Enter Signal', ButtonName)
        if ok:
            self.worker2 = Machs()
            self.worker2.sendCommand('write '+text)
            print ButtonName, "send: ",  unicode(text)
gehts...

Jemand eine Idee warum?
BlackJack

@sandra84: Passiert das beim ersten Kommando das gesendet wird? Kann es sein, dass die "Gegenseite" die Pipes nach einem Kommando, oder vielleicht nach einer gewissen Zeit, schliesst und man über die dann einfach kein zweites Kommando absetzen kann!?
sandra84
User
Beiträge: 17
Registriert: Mittwoch 9. Juni 2010, 06:34

hmmm ja also in der Theorie ja..

Es wird das kommando "quit" gesendet und der task test.out beendet. Aber die sendCommand macht ja wieder Popen etc. (was ich eigentlich der Meinung bin, dass es das gar nicht braucht wg. dem Konstruktor). Hatte das Testhalber nochmal in die sendCommand geschrieben um ebend das mit dem "quit" etc. zu umgehen.
sandra84
User
Beiträge: 17
Registriert: Mittwoch 9. Juni 2010, 06:34

aha! also wenn ich das ganze nicht kill.. dann klappts auch mit der pipe.. warum er aber die sendCommand nicht einfach ohne ein neues Klassen-Objekt nimmt versteh ich nicht. Das Objekt ist ja noch vorhanden zu dem Zeitpunkt und die sendCommand macht ja eine eigene auf.
BlackJack

@sandra84: Ich bin jetzt etwas verwirrt von dem Quelltext, denn in der `__init__()` wird ja auch schon einmal `self.client` gebunden. Und dann nicht verwendet?

Und wie sieht der komplette Traceback aus? Denn die vorletzte Zeile wie Du sagst, kann ja nicht der Punkt für einen IOError sein, höchstens auf dem Aufrufstack dahin der Auslöser.
sandra84
User
Beiträge: 17
Registriert: Mittwoch 9. Juni 2010, 06:34

ne.. also ja..

ich habs mal Testhalber in die sendCommand reingeschrieben. Eigentlich sollte es nur in der init stehen.

Ach der mist ist.. ich kanns nicht so ohne weiteres kopieren :P also den Traceback..

self.worker.sendCommand("read 34")
self.client.stdin.write(cmd + "\n")
IOError: [Errno 32] Broken pipe

wie gesagt, der Fehler ist nun weg, da ich den Prozess der test.out nicht mehr kill, aber
mir will nicht in den Kopf warum das überhaupt ein Problem dargestellt hatte, da die sendCommand eigentlich wieder alles "gestartet" hat.
Antworten