GTK w/ Python 中的线程在 PyGObject 内省中是否发生了变化?

发布于 2024-11-27 19:34:31 字数 2782 浏览 0 评论 0原文

我第一次将程序从 PyGTK 转换为 PyGObject 自省,但在线程方面遇到了障碍。我有一个需要一些时间才能完成的过程,因此我弹出一个带有进度条的对话框,并使用一个线程来执行该过程并更新进度条。这在 PyGTK 中工作得很好,但在转换为 PyGObject 后,我​​得到了所有常见的不正确线程怪异:程序挂起,但它似乎挂在进程的不同部分,等等。所以我觉得有些东西已经改变了,但我可以不明白什么。

这是这个简单的 PyGTK 进度条示例: http://aruiz.typepad.com/siliconisland/ 2006/04/threads_on_pygt.html 正如该页面上所示,代码有效。我已将其转换为 PyGObject 自省,并且遇到了与我的程序中相同的问题:它挂起,它无法正确更新进度条等。

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()

在 Gdk 线程功能的文档中,它强调您首先必须运行 g_thread_init (NULL) 在运行 gdk_threads_init() 之前。但要运行它,您需要链接一些额外的库。如果我尝试通过内省导入 GLib,然后尝试运行 GLib.thread_init(),则会收到以下错误:

>>> 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

我认为这是因为未链接额外的线程库。如果这是我的线程问题的原因,我如何使用 GLib 就好像这些库已链接一样?

I'm in the process of converting a program from PyGTK to PyGObject introspection for the first time and I've hit a roadblock with threading. I have a process that takes some time to complete, so I pop up a dialog with a progress bar on it and I use a thread to do the process and to update the progress bar. This worked fine with PyGTK but after converting to PyGObject, I get all the usual improper threading weirdness: the program hangs, but it seems to hang in different parts of the process, etc. So I get the impression that something has changed but I can't figure out what.

Here's this simple PyGTK progressbar example: http://aruiz.typepad.com/siliconisland/2006/04/threads_on_pygt.html
As presented on that page, the code works. I've converted it to PyGObject introspection and I get the same problems as in my program: it hangs, it doesn't properly update the progress bar, etc.

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()

In the documentation for Gdk's threading capabilities, it stresses that you first must run g_thread_init(NULL) before running gdk_threads_init(). But to run that, you need to link in some extra libraries. If I try to import GLib through introspection and then I try to run GLib.thread_init(), I get the following error:

>>> 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

I assume this is because the extra threading libraries weren't linked. If this is the cause of my threading problems, how can I work with GLib as if those libraries have been linked?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

彻夜缠绵 2024-12-04 19:34:31

我通过浏览一些用 Python 编写的 Gnome 程序(在本例中是 Gnome Sudoku,实际上已经帮助了我几次)设法回答了我自己的问题。

诀窍在于,您必须在代码开头调用 GObject.threads_init(),而不是 C 文档所暗示的 GLib.thread_init()

I managed to answer my own question by poking through some Gnome programs written in Python (Gnome Sudoku, in this case, which actually has helped me a couple of times).

The trick is that you have to call GObject.threads_init() at the beginning of your code, not GLib.thread_init() as the C documentation implies.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文