2011-08-04 14 views
25

Jestem w trakcie przekształcania programu od PyGTK do introspekcji PyGObject po raz pierwszy i trafiłem na blokadę z gwintowaniem. Mam proces, który zajmuje trochę czasu, więc pojawia się okno dialogowe z paskiem postępu i używam wątku, aby wykonać ten proces i zaktualizować pasek postępu. To działało dobrze z PyGTK, ale po konwersji do PyGObject, uzyskuję wszystkie zwykłe niepoprawne dziwactwa: program się zawiesza, ale wydaje się, że jest zawieszony w różnych częściach procesu itp. Mam więc wrażenie, że coś się zmieniło, ale mogę nie wiem co.Czy wątki w GTK w/Pythonie zostały zmienione w introspekcji PyGObject?

Oto prosty przykład paska postępu PyGTK: http://aruiz.typepad.com/siliconisland/2006/04/threads_on_pygt.html Jak przedstawiono na tej stronie, kod działa. Mam przeliczone go do PyGObject introspekcję i mam takie same problemy jak w moim programie: to wisi, nie prawidłowo zaktualizować pasek postępu, itp

import threading 
import random, time 
from gi.repository import Gtk, Gdk 
#Initializing the gtk's thread engine 
Gdk.threads_init() 


class FractionSetter(threading.Thread): 
    """This class sets the fraction of the progressbar""" 

    #Thread event, stops the thread if it is set. 
    stopthread = threading.Event() 

    def run(self): 
     """Run method, this is the code that runs while thread is alive.""" 

     #Importing the progressbar widget from the global scope 
     global progressbar 

     #While the stopthread event isn't setted, the thread keeps going on 
     while not self.stopthread.isSet() : 
      # Acquiring the gtk global mutex 
      Gdk.threads_enter() 
      #Setting a random value for the fraction 
      progressbar.set_fraction(random.random()) 
      # Releasing the gtk global mutex 
      Gdk.threads_leave() 

      #Delaying 100ms until the next iteration 
      time.sleep(0.1) 

    def stop(self): 
     """Stop method, sets the event to terminate the thread's main loop""" 
     self.stopthread.set() 

def main_quit(obj): 
    """main_quit function, it stops the thread and the gtk's main loop""" 
    #Importing the fs object from the global scope 
    global fs 
    #Stopping the thread and the gtk's main loop 
    fs.stop() 
    Gtk.main_quit() 

#Gui bootstrap: window and progressbar 
window = Gtk.Window() 
progressbar = Gtk.ProgressBar() 
window.add(progressbar) 
window.show_all() 
#Connecting the 'destroy' event to the main_quit function 
window.connect('destroy', main_quit) 

#Creating and starting the thread 
fs = FractionSetter() 
fs.start() 

Gtk.main() 

w dokumentacji możliwości gwintowania GDK, w jej podkreśla, że ​​najpierw musisz uruchomić g_thread_init (NULL) przed uruchomieniem gdk_threads_init(). Ale aby to uruchomić, musisz połączyć kilka dodatkowych bibliotek. Jeśli próbuję zaimportować GLib poprzez introspekcję, a potem próbuję uruchomić GLib.thread_init(), pojawia się następujący błąd:

>>> from gi.repository import GLib 
>>> GLib.thread_init(None) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python2.7/site-packages/gi/types.py", line 44, in function 
    return info.invoke(*args) 
glib.GError: Could not locate g_thread_init: `g_thread_init': /usr/lib/libglib-2.0.so.0: undefined symbol: g_thread_init 

Zakładam, to dlatego, że dodatkowe biblioteki do gwintowania nie zostały połączone. Jeśli jest to przyczyną moich problemów z wątkami, jak mogę pracować z GLibem tak, jakby te biblioteki były połączone?

+1

Czy nie powinieneś łączyć wywołania z 'Gtk.main()' z 'Gdk.threads_enter()' i 'Gdk.threads_leave()'? Wszystkie przykłady kodu C, które widziałem, robią to. Np .: http://blogs.operationaldynamics.com/andrew/software/gnome-desktop/gtk-thread-awareness –

Odpowiedz

25

Udało mi się odpowiedzieć na moje własne pytanie, przeglądając niektóre programy Gnome napisane w Pythonie (Gnome Sudoku, w tym przypadku, co faktycznie pomogło mi kilka razy).

Sztuką jest, że musisz zadzwonić pod numer GObject.threads_init() na początku kodu, a nie GLib.thread_init(), jak sugeruje dokumentacja C.

+2

Po prostu chcę podziękować. Człowieku, praca z tym materiałem to 90% Googling. – miracle2k

+0

Dziękuję bardzo! Miałem ten dokładny problem i nie miałem pojęcia, gdzie się źle dzieje. Chciałbym, aby PyGObject miał jakąś specyficzną dokumentację zamiast po prostu "sprawdź C docs". – alldayremix

+1

Nowoczesna aktualizacja tej odpowiedzi: GObject.threads_init() i GLib.threads_init() są synonimami i nie są tak naprawdę potrzebne w PyGObject v3.10.2 i nowszych. Zobacz także: https://wiki.gnome.org/Projects/PyGObject/Threading –