在Python/PyGTK中后台线程运行计算

4
有没有一种方法可以在后台运行Python线程而不会在耗时操作期间锁定Python的其余部分?
我正在尝试在Python(pygtk)应用程序的后台线程中进行耗时计算。我了解线程的工作原理。问题是,每次我在任何线程中运行昂贵的操作(例如:PIL的image.load()用于大型图像),它都会阻塞所有Python线程,直到操作完成,即使它在单独的线程中。
那么,有没有一种方法可以在后台运行Python线程而不会锁定Python的其他部分?(只要它们不锁定我的GUI,我不在乎它们需要多长时间。我不能让我的GUI每隔几秒钟就无响应)。使用sleep语句无效,因为我的问题在于需要很长时间的单个命令(如image.load())。

2
请了解 GIL(全局解释器锁),并可能查看 multiprocessing 包... 如果您使用普通线程,则它们应该共享 CPU 时间... 但是长时间的不可中断调用将会阻塞。 - Joran Beasley
我正在使用Threading模块。我的问题是,在不相关的线程中进行昂贵的操作时,它会锁定所有线程(包括Gui),导致Gui无响应。 - James
1
+1 @JoranBeasley,多进程编程非常类似于线程,因此修改您现有的代码以使用它应该相当简单。 - redrah
非常感谢!我不确定“相当简单”的部分,因为快速地在进程间传输数据是一个挑战,但是Python的多线程包肯定解决了我的问题。 :) - James
2个回答

3

由于您正在使用 pygtk,您是否调用了 threads_init()

对于较新版本:

>>> from gi.repository import GObject
>>> GObject.threads_init()

对于年龄较大的人:

>>> import gobject
>>> gobject.threads_init()

同时确保不要从您的线程中调用任何GUI方法,否则您的应用程序将以奇怪的方式中断。解决此问题的简单方法是使用GObject.idle_add

idle_add(callable, user_data=None, priority=None) -> source id callable接收(user_data)

将可调用对象添加到默认主循环中,每当没有更高优先级的事件等待时调用。


1
谢谢,但我正试图在不阻塞主gtk线程的情况下在后台运行(非gtk)任务。将任务移至主gtk线程作为空闲函数是我所尝试做的反方向操作。 - James
@James,我的意思不是在idle_add回调中运行所有内容。你仍然需要像现在一样运行你的单独线程。但是当该线程需要更新GUI(进度条、标签等)时,只需在idle_add回调中执行此操作即可。 - Mew

1

如果要在后台进行处理,您也可以使用Python的子进程。它将创建一个子进程(独立于原始执行),您可以在特定间隔使用.poll来检查进程是否完成。如果运行.communicate,则整个进程将等待子进程完成。此外,您可以参考此文档:threading-subprocess

我还相信,只需使用Python中的普通线程,就可以解决您的问题。


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