Python线程无法与pygobject一起使用?

4

看一下这个简单的python gobject程序:

import threading
import gobject
import time

def f():
    while True:
        print "HELLO"
        time.sleep(1)
threading.Thread(target=f).start()

gobject.MainLoop().run()

它会生成一个线程,每秒输出“HELLO”,然后进入gobject主循环。问题在于它实际上什么也没做。为什么?
$ python a.py 
[...]

如果我按下CTRL+C键,它就开始工作了。而且,删除程序中的最后一行(gobject.MainLoop().run())也会使其工作。为什么?
$ python a.py 
^CTraceback (most recent call last):
  File "a.py", line 11, in <module>
    gobject.MainLoop().run()
KeyboardInterruptHELLO

HELLO
HELLO
HELLO
[...]

看一下这个第二个程序,它与第一个程序完全相同,只是它告诉gobject每秒运行一次函数g。这个有点起作用,生成的线程偶尔会运行一次,而不是从不运行。为什么?

import threading
import gobject
import time

def f():
    while True:
        print "HELLO"
        time.sleep(1)
threading.Thread(target=f).start()

def g():
    print "yo"
    return True
gobject.timeout_add_seconds(1, g)

gobject.MainLoop().run()

运行它:

$ python b.py 
HELLOyo

yo
yo
yo
 HELLO
yo
yo
yo
yo
yo
yo
yo
 HELLO
yo
yo
yo
yo
^CTraceback (most recent call last):
  File "b.py", line 16, in <module>
    gobject.MainLoop().run()
KeyboardInterrupt
HELLO
HELLO
HELLO
HELLO
HELLO

再次按下CTRL+C,将会使生成的线程起作用。为什么?
这是使用pygobject-2.28.6库。
1个回答

1

使用gobject时,需要初始化线程。要做到这一点,请调用:

gobject.threads_init()

嗯,这似乎解决了问题,但也许只是巧合,可能是由于并发事件顺序的改变。我觉得图书馆会在你使用它之前调用一个函数来破坏整个运行时是荒谬的。此外,“对于希望使用Python线程与GNOME平台交互的应用程序,必须在运行或创建线程和启动主循环之前调用GObject.threads_init()。”并不适用于我的情况,因为我只从主线程中使用gobject。 - Dog
即使在C语言中使用GLib,如果您从多个线程中使用GLib,则必须通过调用g_thread_init()来初始化线程系统。(https://developer.gnome.org/glib/2.30/glib-Threads.html#g-thread-init) - Dog
我不确定为什么一个轻量级的主循环会阻塞所有其他线程,我本以为除非你正确初始化它,否则它在运行时不会释放GIL。但是我真的找不到任何支持这一点的参考资料(除了这里)。 - mata
https://github.com/GNOME/pygobject/blob/master/gi/overrides/GLib.py#L53 表示:“自从版本3.11以后,不再需要调用threads_init。请参见:https://wiki.gnome.org/PyGObject/Threading”。 - Robie Basak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接