gobject idle funktioniert nicht so richtig

Programmierung für GNOME und GTK+, GUI-Erstellung mit Glade.
gugugs
User
Beiträge: 113
Registriert: Dienstag 30. Dezember 2008, 12:38

So, das ist nun der ganze Quellcode:

[Edit (Leonidas): Quellcode ausgelagert.]

Es hilft mir nicht viel Falls mir jetzt jemand sagt, das es unordentlich ist oder die Variablen nicht gut bennant sind (das weiß ich selbst). Alle Funktionen in der Mitte sind eig. uninteressant, was mein Ziel ist, ist die on_download_clicked und die on_upload_clicked Funktion so zu "präparieren" das sie mein Programm nicht einfrieren, falls die Glade Datei noch benötigt wird, würde ich diese auch noch schicken.
Ich denke mal, das es daran liegen könnte, das wenn ich es mit einem Thread mache, ich ja ganze Funktionen übergeben muss, und da diese in der Main Klasse sind, wird diese dann halt aufgehalten

Danke
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

gugugs hat geschrieben:Es hilft mir nicht viel Falls mir jetzt jemand sagt, das es unordentlich ist oder die Variablen nicht gut bennant sind
Deswegen habe ich um ein Minimalbeispiel gebeten. Es ist schon klar dass keiner einen nahezu 1000 Zeilen langen Quelltext analysiert der ohne Glade-Datei nicht mal richtig lauffähig ist.
gugugs
User
Beiträge: 113
Registriert: Dienstag 30. Dezember 2008, 12:38

Die Funktionen sind ziemlich verteilt, sonst wäre es wieder unklar gewesen, aber ich hätte es auslagern können, sry.

Weiß vllt du, oder jemand vllt schon einen Rat?
BlackJack

Ja, aber das willst Du ja nicht hören. ;-)
gugugs
User
Beiträge: 113
Registriert: Dienstag 30. Dezember 2008, 12:38

Falls es mit dem Problem zusammen hängt, sicherlich
BlackJack

Vielleicht mit dem Problem direkt nicht, aber das findet man ja nicht heraus, wenn man sich solch einen Quelltext nicht anschauen möchte, solange der *so* aussieht. :P
gugugs
User
Beiträge: 113
Registriert: Dienstag 30. Dezember 2008, 12:38

Ich denke, das Problem liegt daran, das ich wenn ich eine Funktionen in einen Thread übergeben würde und diese dann dort aufrufe, das er ja dann diese Funktion dann trotzdem in der Hauptklasse ausführt, und diese dann auch zum Stillstand kommt, kann das so sein?
BlackJack

Wenn Du eine Funktion in einem anderen Thread ausführst als dem in dem die Ereignisverarbeitung der GUI läuft, dann darf die GUI nicht blockieren.

Edit: Ich sehe gerade, dass Du in dem Programm überhaupt gar keine Threads verwendest!?
gugugs
User
Beiträge: 113
Registriert: Dienstag 30. Dezember 2008, 12:38

Ja, ich hatte sie wieder weggemacht, weil er nichts gebracht hat. Aber wenn ich die ganze Upload Funktion z.B. in einen Thread mache, und die dazugehörigen anderen Funktionen, die die Upload Funktion benötigt, mit gebe, dann friert der GUI ein... Das habe ich nämlich schon ausprobiert...

Ich habe jetzt zum testen den Code mal so geändert, das ist nur oben:

Code: Alles auswählen

class my_thread(threading.Thread):
	def __init__(self):
		threading.Thread.__init__(self)
	
	def run(self):
		self.xml = gtk.glade.XML(os.path.join(os.path.dirname(sys.argv[0]), "linkcc_0.2.2.glade"))
		
		self.window=self.xml.get_widget("progressbar")
		self.window.show_all()

class programm:
........
.....
...
....
Wenn ich den Thread nun mit dr Upload Funktion starte, dann öffnet sich das Fenster erst, wenn in der Upload Funktion alles abgelaufen ist, und dort alles fertig ist. Vorher bleibt das Fenster weg. Müsste sich das Fenster nicht eig. öffen? Habe in der on_upload_clicked Funktion den Thread ganz normal an erster Stelle aufgerufen, und trotzdem klappt es nicht.
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Du zeigst hier nicht, wie du den Thread startest. Rufst du z.B. die `run`-Methode anstatt der `start`-Methode auf, dann wird da kein neuer Thread gestartet, sondern die `run`-Methode wir im selben Thread augeführt. Und grundsätzlich ist es eine schlechte Idee, mit mehreren Threads gleichzeitig auf die GUI zuzugreifen. Wurde aber schön öfters im Forum diskutiert, die Suchfunktion liefert da bestimmt etwas.
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
gugugs
User
Beiträge: 113
Registriert: Dienstag 30. Dezember 2008, 12:38

Ok, das mit dem Progress Bar war jetzt ein sehr blödes Beispiel, den im Prinzip greife ich ja nicht mal auf den GUI zu, sondern er lädt nur Dateien auf einen Server, ich starte den Thread so:

Code: Alles auswählen

thread=my_thread()
thread.start()
ist das falsch?


edit: mir ist aufgefallen, wenn ich zu Testzwecken einfach mal diese Thread in genau mein Programm einbaue also:

Code: Alles auswählen

class my_thread(threading.Thread):
	def __init__(self):
		threading.Thread.__init__(self)
		
	def run(self):
		i=0
		for i in range(5):
			time.sleep(1)
			i=i+1
			print i
		print "fertig"

class programm:
.........
......
....
	starte_thread=my_thread()
	starte_thread.start()

Wenn ich diesen Thread starte, passiert nichts... Erst wenn ich einmal strg+c drücke, dann laufen die Zahlen, an was kann das liegen?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

gugugs, gewöhn dir an funktionsfähige Minimalbeispiele zu posten. Ich werde deinen Code nicht mehr erweitern bis es geht, weil es dann nicht reproduzierbar ist:

Code: Alles auswählen

import threading, time

class my_thread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        i=0
        for i in range(5):
            time.sleep(1)
            i=i+1
            print i
        print "fertig"

starte_thread=my_thread()
starte_thread.start()
Funktioniert hier nämlich problemlos.
gugugs
User
Beiträge: 113
Registriert: Dienstag 30. Dezember 2008, 12:38

Sry, also es klappt jetzt, mein Problem war, das ich

Code: Alles auswählen

gobject.threads_init()
nicht benutzt habe. Wenn man einen Thread hat der nicht viel machen soll, geht es auch ohne. Aber wenn der Thread länger braucht, um etwas zu machen, gibt es unter GTK große Probleme, also er führt den Thread dann überhaupt nicht aus. Damit geht nun alles problemlos, noch mal danke für den ganzen Stress mit mir kompliziertem Jungen :D

Jetzt stehe ich leider vor einem neuen Problem, und zwar, bekomme, ich wenn ich diese Funktion in einem Thread öfters hintereinander aufrufe, einen Speicherzugriffsfehler, aber sehr sporadisch. Hier die Funktion:


Code: Alles auswählen

	def homemake_list(self, dname=None):
		if not dname:
			self.homedirname=os.path.expanduser("~")
		else:
			self.homedirname=os.path.abspath(dname)
		files=[f for f in os.listdir(self.homedirname) if f[0] <> "."]
		filestat=os.stat(self.homedirname)
		self.homeliststore.clear()
		self.homeliststore.append(["..", filestat.st_size, oct(stat.S_IMODE(filestat.st_mode)), time.ctime(filestat.st_mtime)])
		for f in files:
			filename=os.path.join(self.homedirname, f)
			filestat=os.stat(filename)
			self.homeliststore.append([f, filestat.st_size, oct(stat.S_IMODE(filestat.st_mode)), time.ctime(filestat.st_mtime)])
Den dazugehörigen TreeView mache ich so:

Code: Alles auswählen

		self.homeliststore=gtk.ListStore(str, str, str, str)
		self.hometreeview=gtk.TreeView(self.homeliststore)
		self.hometreeview.connect("row-activated", self.homeopen)
		self.ftp_menu_client=self.xml.get_widget("ftp_menu_client")
		self.hometreeview.connect_object("button-press-event", self.homerigth_click, self.ftp_menu_client)
		self.hometreeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)

		self.hometvcolumn=[]
		self.hometvcolumn.append(" ")
		self.hometvcolumn.append(gtk.TreeViewColumn("Name"))
		self.hometvcolumn.append(gtk.TreeViewColumn("Size"))
		self.hometvcolumn.append(gtk.TreeViewColumn("Mode"))
		self.hometvcolumn.append(gtk.TreeViewColumn("Last Changed"))

		for i in range(1, 5):
			self.hometreeview.append_column(self.hometvcolumn[i])
			
		self.homecell = gtk.CellRendererText()
		for i in range(1,5):
			self.hometvcolumn[i].pack_start(self.homecell, True)
			
		for i in range(1,5):
			self.hometvcolumn[i].set_attributes(self.homecell, text=i-1)
			
		self.vbox17=self.xml.get_widget("vbox17")
		self.homescrolledwindow1=gtk.ScrolledWindow()
		self.homescrolledwindow1.add(self.hometreeview)
		self.vbox17.pack_start(self.homescrolledwindow1)
(self.xml ist die glade Datei)

Den Thread rufe ich so auf:

Code: Alles auswählen

		gobject.threads_init()
		thread=cl_act_thread(self.homemake_list, self.progressbar2)
		thread.start()
und der Thread sieht dann so aus:

Code: Alles auswählen

class cl_act_thread(threading.Thread):
	def __init__(self, homemake, progressbar):
		threading.Thread.__init__(self)
		self.homemake_list=homemake
		self.progressbar=progressbar
		
	def run(self):
		self.end_status=0
		
		def progress(progress):
			progress.pulse()
			if self.end_status==0:
				return True
			else:
				progress.set_fraction(0)
				progress.set_fraction(0.2)
				return False
		
		gobject.timeout_add(50, progress, self.progressbar)
		self.homemake_list()
		time.sleep(0.5)
		self.end_status=1
Tut mir leid, dass das jetzt alles so einzeln ist. Aber im Programm ist das leider alles sehr verteilt. Die Funktionen so, ohne alles drum und dran, habe ich noch nicht ausprobiert.

Ich habe im Internet schon Beiträge so einem Fehler von Firefox gefunden, bei dem es auch um Speicherzugriffsfehler ging. Da hieß es, das es am GTK Theme liegen könnte, und das es ging, wenn man es als Root startet. Ging aber bei leider auch nicht. Dann habe ich Beiträge gefunden, das es am Ram liegen könnte. Kann aber eig. auch nicht sein, da der Fehler sonst auch bei andren Programmen gekommen wäre. Dann habe ich bei einem Beitrag gesehen, das jemand ein Programm geschrieben hat, bei dem es keine Speicherverwaltung gab. Was ist Speicherverwaltung bei Python? Habe von so etwas nie gehört.


Danke für jede Hilfe.

edit: Manchmal steht nur

bash: line 1: 7089 Speicherzugriffsfehler /usr/bin/python "datei.py"

und manchmal kommt

sys:1: GtkWarning: gtk_list_store_get_value: assertion `VALID_ITER (iter, list_store)' failed
sys:1: Warning: g_object_set_property: assertion `G_IS_VALUE (value)' failed
sys:1: Warning: g_value_unset: assertion `G_IS_VALUE (value)' failed
bash: line 1: 7089 Speicherzugriffsfehler /usr/bin/python "datei.py"
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

gugugs hat geschrieben:Dann habe ich bei einem Beitrag gesehen, das jemand ein Programm geschrieben hat, bei dem es keine Speicherverwaltung gab. Was ist Speicherverwaltung bei Python? Habe von so etwas nie gehört.
In Python ist die Speicherverwaltung automatisch, d.h. der Interpreter kümmert sich selbst darum, so viel Speicher wie nötig anzufordern und auch wieder freizugeben, wenn er nicht mehr nötig ist.
gugugs hat geschrieben:sys:1: GtkWarning: gtk_list_store_get_value: assertion `VALID_ITER (iter, list_store)' failed
sys:1: Warning: g_object_set_property: assertion `G_IS_VALUE (value)' failed
sys:1: Warning: g_value_unset: assertion `G_IS_VALUE (value)' failed
bash: line 1: 7089 Speicherzugriffsfehler /usr/bin/python "datei.py"
Könnte ein Bug in PyGTK oder GTK+ sein, da scheint die Speicherverwaltung des C-Codes fehlerhaft zu sein. Kannst also entweder mit den GTK-Leuten sprechen, dass die den Bug korrigieren oder dein Programm entwursteln, dass es den Bug nicht mehr hervorruft.
gugugs
User
Beiträge: 113
Registriert: Dienstag 30. Dezember 2008, 12:38

Habe es nun auf zwei anderen Rechnern getestet, da passiert nichts, läuft dort einwandfrei.

Zum Thema entwursteln. Was für Gründe können es sein, wenn so Fehler auftreten? Also allgemein? Kann dieser Speicherzugriffsfehler kommen, wenn man allgemein, einen unordentlichen Code schreibt, oder kann man das ein wenig, spezialisieren, das man sagen kann, es kommt von bestimmtem Kombinationen?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

gugugs hat geschrieben:Habe es nun auf zwei anderen Rechnern getestet, da passiert nichts, läuft dort einwandfrei.
GTK/PyGTK-Versionen geprüft? Vielleicht wurde das dort bereits ausgebessert oder es wird anderer Code verwendet (zum Beispiel unter einem anderen OS).
gugugs hat geschrieben:Also allgemein? Kann dieser Speicherzugriffsfehler kommen, wenn man allgemein, einen unordentlichen Code schreibt, oder kann man das ein wenig, spezialisieren, das man sagen kann, es kommt von bestimmtem Kombinationen?
Scher zu sagen, da ich mir deine 1000 Zeilen nicht wirklich antun will, aber die Closure die du da als Callback übergibst könnte eine Problemursache sein. Oder irgendetwas anderes. Jedenfalls sollte der Interpreter in Python nie mit einem solchen Fehler beendet werden, also ist da auf C-Ebene irgendein Bug aufgetreten.

(Sowas hatte ich damals auf wx unter Windows am laufenden Band und lustigerweise haben alle meine Versuche diese Bugs anders zu umgehen wiederrum zu anderen Bugs geführt. Ziemlich frustrierend. Ist aber schon eine Zeitlang her).
gugugs
User
Beiträge: 113
Registriert: Dienstag 30. Dezember 2008, 12:38

Sollte man das jetzt möglichst unterlassen? Oder kann man da weiter machen, in der Hoffnung, das es wirklich an dem PC lag, mit dem es getestet wurde. Wie hoch ist denn die Wahrscheinlichkeit, das es am RAM an pygtk, oder am Code liegt? Also was trifft denn eher zu? Denn ich bin mir gar nicht so unsicher, das es an meinem RAM liegen könnte. Hab aber noch kein memtest gemacht.
aber die Closure die du da als Callback übergibst könnte eine Problemursache sein.
In wie fern?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

gugugs hat geschrieben:Sollte man das jetzt möglichst unterlassen? Oder kann man da weiter machen, in der Hoffnung, das es wirklich an dem PC lag, mit dem es getestet wurde. Wie hoch ist denn die Wahrscheinlichkeit, das es am RAM an pygtk, oder am Code liegt?
Ähm, wer sollte das wissen?
gugugs hat geschrieben:
aber die Closure die du da als Callback übergibst könnte eine Problemursache sein.
In wie fern?
Vermutung. Closures sind ja in C eher nicht alltäglich, vielleicht räumt da also irgendein C-Code die Closure weg und versucht danach darauf zuzugreifen. Keine Ahnung, war nur eine Schätzung.
gugugs
User
Beiträge: 113
Registriert: Dienstag 30. Dezember 2008, 12:38

Ich weiß leider nicht so genau, was Closures sind, beziehungsweise, was ich darunter verstehe. Wie kann ich das Problem am besten angehen?

edit: wenn ich das richtig verstehe, dann geht dieser Beitrag http://de.wikipedia.org/wiki/Closure in etwa in meine Richtung? Denn so ganz habe ich das noch nicht verstanden
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

gugugs hat geschrieben:Iedit: wenn ich das richtig verstehe, dann geht dieser Beitrag http://de.wikipedia.org/wiki/Closure in etwa in meine Richtung? Denn so ganz habe ich das noch nicht verstanden
Eine Closure ist vereinfacht gesagt eine Funktion in einer Funktion.
Antworten