开发者

Which GUI frameworks are best for a multi-threaded Python program?

I am writing a multi-threaded Python program with a GUI, with several modules that "touch" the GUI by changing text and background colors. I am currently using PyGTK and am finding that the GUI sometimes开发者_运维知识库 crashes "silently" (no error messages; the program just terminates), and sometimes encounters segmentation faults.

This site notes that GTK is not completely thread-safe, and that PyGTK multi-threaded programming is tricky. Are there better Python GUI frameworks for multi-threaded programs that are less likely to produce problems?


Ohh, I definitely recommend PyQt4. At first, I didn't get all this SIGNAL and EMIT nonsense, but now that I've made a program with it, the QThread module is amazingly useful.

As for stability, I have never had a crash, ever. Even while I was debugging half-functional code, QT didn't have any problems. It just threw an error to the console window whenever I clicked a button with an invalid signal slot.

GTK, on the other hand, just 'sploded once in a while with no errors whatsoever. Just your extremely descriptive and friendly Segmentation Fault. That was one of the reasons I find PyQt a joy to work with. When you get an error, you actually know what's wrong.

I'm pretty sure it's personal preference after that, but one more plus is native-looking GUIs on Mac, Linux, and Windows. GTK+ on Windows (don't get me wrong. I use Ubuntu) just has this X-org feel to it, which disturbs me.

Good luck!


Just to make PyQt a bit more attractive, here's an excerpt from my book binding application (it's a bit messy):

class Binder(QtCore.QThread):
  '''
  Class for binding the actual book
  '''

  def __init__(self, parent = None):
    super(Binder, self).__init__(parent)



  def initialize(self, pages, options, outfile):
    self.pages = pages
    self.options = options
    self.outFile = outfile

    self.book = organizer.Book()
    self.enc = Encoder(self.options)
    self.ocr = ocr.OCR(self.options)

    self.connect(self.enc, QtCore.SIGNAL('updateProgress(int, int)'), self.updateProgress)



  def updateProgress(self, percent, item):
    self.emit(QtCore.SIGNAL('updateProgress(int, QString)'), int(percent), 'Binding the book...')
    self.emit(QtCore.SIGNAL('updateBackground(int, QColor)'), int(item), QtGui.QColor(170, 255, 170, 120))

    if int(percent) == 100:
      time.sleep(0.5)
      self.emit(QtCore.SIGNAL('finishedBinding'))



  def run(self):
    self.die = False

    for page in self.pages:
      self.add_file(page, 'page')

    if not self.die:
      self.analyze()

    if not self.die:
      self.book.get_dpi()

    if self.options['ocr'] and not self.die:
      self.get_ocr()

    if not self.die:
      self.enc.initialize(self.book, self.outFile)
      self.enc.start()


If you are updating the GUI from a thread, you might want to use gobject.idle_add() so that the GUI update function is called later in the loop, most GUI frameworks (like Qt) require you to add a callback that will be called later when the mainloop is idle. GTK also supports calling the GUI functions from threads by using the gtk.gdk.lock context manager or calling gtk.gdk.threads_enter and gtk.gdk.threads_leave around your GUI calls.

So you either do:

gobject.idle_add(lambda: window.whatever(arg1, arg2))

Or you do:

with gtk.gdk.lock:
    window.whatever(arg1, arg2)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜