Python进度条的最佳实践&x27;斯皮格特克

Python进度条的最佳实践&x27;斯皮格特克,python,multithreading,Python,Multithreading,我希望得到其他人对如何在Python的PyGTK中实现进度条的最佳实践的意见的反馈 进度条所代表的工作在计算上非常重要。因此,我希望在一个单独的进程中完成这项工作(从而使操作系统能够在不同的内核上运行它)。我希望能够开始工作,然后在等待结果的同时继续使用GUI执行其他任务 我见过许多人间接地问这个问题,但我没有看到任何具体的专家建议。我希望通过问这个问题,我们将看到一个社区的综合专业知识。我现在意识到,我没有足够的声誉使这成为一个社区维基,所以我希望其他人可以将其更改为维基状态。谢谢 我决不是一

我希望得到其他人对如何在Python的PyGTK中实现进度条的最佳实践的意见的反馈

进度条所代表的工作在计算上非常重要。因此,我希望在一个单独的进程中完成这项工作(从而使操作系统能够在不同的内核上运行它)。我希望能够开始工作,然后在等待结果的同时继续使用GUI执行其他任务


我见过许多人间接地问这个问题,但我没有看到任何具体的专家建议。我希望通过问这个问题,我们将看到一个社区的综合专业知识。

我现在意识到,我没有足够的声誉使这成为一个社区维基,所以我希望其他人可以将其更改为维基状态。谢谢

我决不是一个专业的Python程序员,但是我花了一些时间试图找到一个可接受的解决方案。我希望以下代码可以作为讨论的起点

import gobject
import pygtk
pygtk.require('2.0')
import gtk
import multiprocessing
import threading
import time

gtk.gdk.threads_init()

class Listener(gobject.GObject):
    __gsignals__ = {
        'updated' : (gobject.SIGNAL_RUN_LAST,
                     gobject.TYPE_NONE,
                     (gobject.TYPE_FLOAT, gobject.TYPE_STRING)),
        'finished': (gobject.SIGNAL_RUN_LAST,
                     gobject.TYPE_NONE,
                     ())
    }

    def __init__(self, queue):
        gobject.GObject.__init__(self)
        self.queue = queue

    def go(self):
        print "Listener has started"
        while True:
            # Listen for results on the queue and process them accordingly                            
            data = self.queue.get()
            # Check if finished                                                                       
            if data[1]=="finished":
                print "Listener is finishing."
            self.emit("finished")
            return
            else:
                self.emit('updated', data[0], data[1])

gobject.type_register(Listener)

class Worker():
    def __init__(self, queue):
        self.queue = queue

    def go(self):
        print "The worker has started doing some work (counting from 0 to 9)"
        for i in range(10):
        proportion = (float(i+1))/10
        self.queue.put((proportion, "working..."))
            time.sleep(0.5)
        self.queue.put((1.0, "finished"))
        print "The worker has finished."


class Interface:
    def __init__(self):
        self.process = None
        self.progress = gtk.ProgressBar()
        button = gtk.Button("Go!")
        button.connect("clicked", self.go)
        vbox = gtk.VBox(spacing=5)
        vbox.pack_start(self.progress)
        vbox.pack_start(button)
        vbox.show_all()
        self.frame = vbox

    def main(self):
        window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        window.set_border_width(10)
        window.add(self.frame)
        window.show()
        window.connect("destroy", self.destroy)

        gtk.main()

    def destroy(self, widget, data=None):
        gtk.main_quit()


    def callbackDisplay(self, obj, fraction, text, data=None):
        self.progress.set_fraction(fraction)
        self.progress.set_text(text)

    def callbackFinished(self, obj, data=None):
        if self.process==None:
            raise RuntimeError("No worker process started")
        print "all done; joining worker process"
        self.process.join()
        self.process = None

        self.progress.set_fraction(1.0)
        self.progress.set_text("done")

   def go(self, widget, data=None):
        if self.process!=None:
            return

        print "Creating shared Queue"
        queue = multiprocessing.Queue()

        print "Creating Worker"
        worker = Worker(queue)

        print "Creating Listener"
        listener = Listener(queue)
        listener.connect("updated",self.callbackDisplay)
        listener.connect("finished",self.callbackFinished)

        print "Starting Worker"
        self.process = multiprocessing.Process(target=worker.go, args=())
        self.process.start()

        print "Starting Listener"
        thread = threading.Thread(target=listener.go, args=())
        thread.start()

if __name__ == '__main__':
    gui = Interface()
    gui.main()
我发现一些有用的参考资料包括:


这更像是堆栈溢出的问题。即使你要求最好的,最好的可能是主观的,在这种情况下,你实际上解释了什么是最适合你的。Eep。如果在PyGTK中使用线程,则需要非常小心。使用gtk.gdk.lock:启动主循环,ie位于
中。任何导致UI变化的调用,包括信号发射,也需要在这样的块中。在开始主循环之前,您需要调用
gtk.gdk.threads_init()
。它工作得非常好,只需说在4行中缺少一些缩进,但是做得很好!