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

Beitragvon gugugs » Sonntag 1. Februar 2009, 00:14

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
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Sonntag 1. Februar 2009, 00:40

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

Beitragvon gugugs » Sonntag 1. Februar 2009, 00:43

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

Beitragvon BlackJack » Sonntag 1. Februar 2009, 00:55

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

Beitragvon gugugs » Sonntag 1. Februar 2009, 00:57

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

Beitragvon BlackJack » Sonntag 1. Februar 2009, 11:14

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

Beitragvon gugugs » Sonntag 1. Februar 2009, 13:37

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

Beitragvon BlackJack » Sonntag 1. Februar 2009, 13:46

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

Beitragvon gugugs » Sonntag 1. Februar 2009, 14:27

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

Beitragvon Trundle » Montag 2. Februar 2009, 13:46

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

Beitragvon gugugs » Dienstag 3. Februar 2009, 13:56

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?
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Dienstag 3. Februar 2009, 18:22

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

Beitragvon gugugs » Donnerstag 5. Februar 2009, 19:03

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"
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Donnerstag 5. Februar 2009, 19:21

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

Beitragvon gugugs » Donnerstag 5. Februar 2009, 19:27

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?

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder