哪些 GUI 框架最适合多线程 Python 程序?

Posted

技术标签:

【中文标题】哪些 GUI 框架最适合多线程 Python 程序?【英文标题】:Which GUI frameworks are best for a multi-threaded Python program? 【发布时间】:2011-01-28 22:41:18 【问题描述】:

我正在编写一个带有 GUI 的多线程 Python 程序,其中有几个模块通过更改文本和背景颜色来“触摸”GUI。我目前正在使用 PyGTK,发现 GUI 有时会“静默”崩溃(没有错误消息;程序只是终止),有时会遇到分段错误。

This site 指出 GTK 不是完全线程安全的,而且 PyGTK 多线程编程很棘手。对于不太可能产生问题的多线程程序,是否有更好的 Python GUI 框架?

【问题讨论】:

GTK 不是线程安全的,但它是线程感知的,因此您绝对可以使用 GTK 编写多线程代码;但是是的,使用 GTK 编写多线程代码实际上可能会很棘手,无论您是否尝试使用 GTK 编写多线程代码,您都会发现自己就像这样:) 【参考方案1】:

哦,我绝对推荐PyQt4。起初,我并没有得到所有这些SIGNALEMIT 的废话,但现在我已经用它编写了一个程序,QThread 模块非常有用。

至于稳定性,我从来没有发生过崩溃。即使我在调试半功能代码,QT 也没有任何问题。每当我单击带有无效信号槽的按钮时,它都会向控制台窗口抛出错误。

另一方面,GTK 只是偶尔“爆发”一次,没有任何错误。只是您极具描述性和友好性的Segmentation Fault。这也是我发现 PyQt 工作愉快的原因之一。当您遇到错误时,您实际上知道出了什么问题。

我很确定这是个人喜好,但另外一个优点是 Mac、Linux 和 Windows 上的原生 GUI。 Windows 上的 GTK+(不要误会我的意思。我使用的是 Ubuntu)对它有一种 X-org 的感觉,这让我感到不安。

祝你好运!


只是为了让 PyQt 更有吸引力,这里摘录我的装订应用程序(有点乱):

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

【讨论】:

信号和槽远非无意义,最近的 PyQt 和 PySide 为它们提供了非常好的接口。 还可以看看新的 PyQts 新样式信号,它使 Signal 和 Slots 的使用不那么冗长:***.com/questions/4031489/… 太好了,看起来很有希望。我现在正在学习教程。 我用 PyQT4 重新实现了我的 GUI,它似乎运行良好。 Qt Designer 与 pyuic4 相结合,相当容易学习。根据 Stack Overflow 和其他地方的讨论,似乎最好使用 PyQt4 QThread 模块;因为我已经有其他模块使用 Python 的 threading.Thread,所以我使用队列来修改 PyQt4 线程(参见 informit.com/articles/article.aspx?p=30708&seqNum=3;需要对 PyQt4 进行一些细微修改)。到现在为止还挺好。谢谢! PyQt 很强大,因为它很简单。这就是我使用它的原因。如果你想修改我的应用程序(我正在清理代码,所以它可能会很乱),你可以在这里找到它:blender3d.github.com/Bindery。祝你好运!【参考方案2】:

如果您从线程更新 GUI,您可能希望使用 gobject.idle_add() 以便稍后在循环中调用 GUI 更新函数,大多数 GUI 框架(如 Qt)要求您添加一个回调稍后在主循环空闲时调用。 GTK 还支持通过使用gtk.gdk.lock 上下文管理器或在您的GUI 调用周围调用gtk.gdk.threads_entergtk.gdk.threads_leave 从线程调用GUI 函数。

所以你要么这样做:

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

或者你这样做:

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

【讨论】:

在 GTK+ 中,如果您想从主线程外部更新 UI,则需要 g_threads_enter,leave,否则您的应用程序可能会随机崩溃并出现非常奇怪的错误消息或没有错误消息。但是,它们在 Windows 中不受支持,因此对于跨平台应用程序,您必须使用 g_idle_add。 哦,对了,现在我记得我在我的应用程序中调用了 g_threads_enter/g_threads_leave,这就是它起作用的原因。我会把它添加到我的答案中,谢谢。

以上是关于哪些 GUI 框架最适合多线程 Python 程序?的主要内容,如果未能解决你的问题,请参考以下文章

Python GUI编程:音乐播放器(多线程爬虫进度条文件)

Python GUI编程:音乐播放器(多线程爬虫进度条文件)

如何在框架关闭时终止或杀死python GUI应用程序中的子线程

python selenium框架解决ip代理框不能自动化登录,解决pyautogui开不了多线程问题

Python Qt GUI设计:多线程中信号与槽的使用(基础篇—9)

Python Qt GUI设计:QTimer计时器类QThread多线程类和事件处理类(基础篇—8)