Какие структуры GUI лучше всего подходят для многопоточной программы на Python? - PullRequest
2 голосов
/ 29 января 2011

Я пишу многопоточную программу на Python с графическим интерфейсом, с несколькими модулями, которые «касаются» графического интерфейса путем изменения цвета текста и фона.В настоящее время я использую PyGTK и обнаруживаю, что графический интерфейс иногда вылетает «тихо» (без сообщений об ошибках; программа просто завершается), а иногда встречается с ошибками сегментации.

Этот сайт отмечает, что GTK не является полностью поточно-ориентированным, и что многопоточное программирование PyGTK сложно.Существуют ли лучшие среды Python GUI для многопоточных программ, которые с меньшей вероятностью могут создавать проблемы?

Ответы [ 2 ]

4 голосов
/ 29 января 2011

Ох, я определенно рекомендую PyQt4 .Сначала я не воспринимал всю эту ерунду SIGNAL и EMIT, но теперь, когда я создал программу с ней, модуль QThread невероятно полезен.

Что касается стабильности, у меня никогда не было сбоев, никогда.Даже когда я отлаживал полуфункциональный код, у QT не было никаких проблем.Он просто выдавал ошибку в окне консоли всякий раз, когда я нажимал кнопку с недопустимым сигнальным слотом.

GTK, с другой стороны, просто «время от времени» всплывал без каких-либо ошибок.Просто ваш чрезвычайно информативный и дружелюбный Segmentation Fault.Это было одной из причин, по которым я нахожу PyQt радостью для работы.Когда вы получаете сообщение об ошибке, вы на самом деле знаете, в чем дело.

Я почти уверен, что после этого это личное предпочтение, но еще один плюс - это выглядящие нативно графические интерфейсы на Mac, Linux и Windows.GTK + в Windows (не поймите меня неправильно. Я пользуюсь 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()
0 голосов
/ 29 января 2011

Если вы обновляете графический интерфейс из потока, вы можете использовать gobject.idle_add(), чтобы функция обновления графического интерфейса вызывалась позже в цикле, большинство структур графического интерфейса (таких как Qt) требуют добавления обратного вызова, который будет вызывается позже, когда основной цикл простаивает. GTK также поддерживает вызов функций GUI из потоков с помощью диспетчера контекста gtk.gdk.lock или вызовов gtk.gdk.threads_enter и gtk.gdk.threads_leave вокруг вызовов GUI.

Так что вы либо делаете:

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

Или вы делаете:

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