2011-01-07 2 views
9

Кто-нибудь использовал PyQt с gevent? Как связать петлю PyQt с gevent?Использование PyQt с gevent

http://www.gevent.org/ - сетевая библиотека Python на основе сопрограмм, использующая greenlet для предоставления синхронного API высокого уровня поверх цикла событий libevent.

+0

Что такое "gevent"? Пожалуйста, добавьте ссылки на ваш вопрос. –

+0

http://www.gevent.org/ - корпоративная сетевая библиотека Python, использующая greenlet для предоставления синхронного API высокого уровня поверх цикла событий Libevent. –

+0

очень интересно .. что вы будете делать, когда pyqt + gevent работает? – linjunhalida

ответ

2

Вот как бы вы изменили PyQt на собственном примере в сессии1 к сотрудничеству: https://github.com/traviscline/pyqt-by-example/commit/b5d6c61daaa4d2321efe89679b1687e85892460a

+2

Это может привести к 100% загрузке процессора без какой-либо полезной активности, поскольку вы не используете период 'gevent.sleep' больше нуля. – fviktor

+0

Запуск цикла событий Qt в гриле не работает, я испытал seg-ошибки, и он блокируется при открытии модального диалога. – mguijarr

1

вы sould избежать использования app.exec_(), это функция цикла, которые используют эту функцию для обработки событий:

http://doc.qt.nokia.com/stable/qcoreapplication.html#processEvents

так что вы можете позвонить processEvents напрямую.

+1

Он может легко привести к 100% загрузке процессора без какой-либо активности. – fviktor

4

Вы можете использовать IDLE «таймер» Qt, чтобы gevent для обработки своей микронити пока нет событий Qt не обрабатываются в течение короткого периода времени, пример 10 миллисекунд. Он все еще не идеален, поскольку он не дает «плавной» возможной интеграции. Это связано с тем, что мы не используем ни одного цикла событий для Qt и gevent, просто «чередуя» их во времени.

Правильное решение было бы позволить libevent прослушивать новые события Qt каким-то образом, но я пока не мог понять, как это сделать на практике. Возможно, Qt отправит что-то в gevent через сокет, когда событие GUI поступит в очередь событий. Кто-нибудь решил это?

Рабочий пример:

""" Qt - gevent event loop integration using a Qt IDLE timer 
""" 

import sys, itertools 

import PySide 
from PySide import QtCore, QtGui 

import gevent 

# Limit the IDLE handler's frequency while still allow for gevent 
# to trigger a microthread anytime 
IDLE_PERIOD = 0.01 

class MainWindow(QtGui.QMainWindow): 

    def __init__(self, application): 

     QtGui.QMainWindow.__init__(self) 

     self.application = application 

     self.counter = itertools.count() 

     self.resize(400, 100) 
     self.setWindowTitle(u'Counting: -') 

     self.button = QtGui.QPushButton(self) 
     self.button.setText(u'Reset') 
     self.button.clicked.connect(self.reset_counter) 

     self.show() 

    def counter_loop(self): 

     while self.isVisible(): 
      self.setWindowTitle(u'Counting: %d' % self.counter.next()) 
      gevent.sleep(0.1) 

    def reset_counter(self): 

     self.counter = itertools.count() 

    def run_application(self): 

     # IDLE timer: on_idle is called whenever no Qt events left for processing 
     self.timer = QtCore.QTimer() 
     self.timer.timeout.connect(self.on_idle) 
     self.timer.start(0) 

     # Start counter 
     gevent.spawn(self.counter_loop) 

     # Start you application normally, but ensure that you stop the timer 
     try: 
      self.application.exec_() 
     finally: 
      self.timer.stop() 

    def on_idle(self): 

     # Cooperative yield, allow gevent to monitor file handles via libevent 
     gevent.sleep(IDLE_PERIOD) 

def main(): 

    application = QtGui.QApplication(sys.argv) 
    main_window = MainWindow(application) 
    main_window.run_application() 

if __name__ == '__main__': 
    main() 
1

Я выпустил проект под названием eventlet-pyqt. Надеюсь, это может быть полезно для тех, кто хочет использовать greenlet в своем приложении PyQt. Я также попробовал gevent, но мне было сложно написать плагин для libevent из-за моего плохого опыта работы на C. Основная проблема с использованием QApplicaton::processEvents() или нулевого интервала QTimer - это программа, запущенная в бесконечный цикл, вызывает 100% использование ядра ЦП. Чтобы этого избежать, я написал новый концентратор для замены функции select() с помощью PyQt's QSocketNotifier. Надеюсь, это сообщение может помочь кому-то.

2

Я пробовал следующий подход: иметь «PyQt backend» для gevent, т.е. реализация цикла gevent с использованием конструкций PyQt, таких как QSocketNotifier, QTimer и т. д. вместо цикла libev. Наконец, я нашел это намного проще, чем делать наоборот, и производительность очень хорошая (цикл Qt основан на glib под Linux, это не так уж плохо).

Вот ссылка на проект на GitHub для тех, кто заинтересован: https://github.com/mguijarr/qtgevent

Это только начало, но она хорошо работает для тестов, которые я сделал. Я был бы рад, если бы люди с большим опытом работы с gevent и PyQt могли бы внести свой вклад.

+0

Это работает для меня из коробки, спасибо человеку! – Lepi

Смежные вопросы