En utilisant PyQt avec gevent
Question
Est-ce que quelqu'un utilise PyQt avec gevent? Comment lier boucle PyQt au gevent?
http://www.gevent.org/ - bibliothèque réseau Python basée coroutine qui utilise Greenlet à fournir une API synchrone de haut niveau sur le dessus de la boucle d'événement libevent.
La solution
Voici comment vous changeriez pyqt par le session1 par exemple à coopérer: https: // github.com/traviscline/pyqt-by-example/commit/b5d6c61daaa4d2321efe89679b1687e85892460a
Autres conseils
Vous pouvez utiliser un « timer » IDLE Qt pour permettre gevent
pour le traitement de ses microfiletages en aucun événement Qt pour une période manutentionnés peu de temps, par exemple 10 millisecondes. Il est pas encore parfait, car il ne donne pas le « lisse » intégration possible. Il est parce que nous n'utilisons une seule boucle d'événement pour les Qt et gevent, juste « imbriquer » les temps.
La bonne solution serait de permettre libevent d'écouter les nouveaux événements Qt en quelque sorte, mais je n'ai pas été en mesure de savoir comment faire encore dans la pratique. Peut-être avoir Qt envoyer quelque chose à gevent via une prise lorsqu'un événement GUI arrive dans la file d'attente événement serait utile. Quelqu'un at-il résolu cela?
Exemple de travail:
""" 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()
J'ai essayé l'approche suivante: avoir un « back-end PyQt » pour gevent, à savoir. une mise en œuvre de la boucle gevent faisant usage de constructions PyQt comme QSocketNotifier, QTimer, etc. au lieu de la boucle de libev. Enfin je l'ai trouvé beaucoup plus facile que de faire le contraire, et la performance est très bonne (la boucle de Qt est basé sur le glib sous Linux, il est pas si mal).
Voici le lien vers le projet sur GitHub pour les personnes intéressées: https://github.com/mguijarr/qtgevent
Ceci est juste un début, mais il fonctionne bien pour les tests que j'ai fait. Je serais heureux si les gens avec plus d'expérience avec gevent et PyQt pourraient contribuer.
sould éviter l'utilisation app.exec_ (), il est une fonction de boucle qui utilisent cette fonction pour des événements de processus:
http://doc.qt.nokia.com/stable/qcoreapplication. html # processEvents
de sorte que vous pouvez appeler directement processEvents.
Je publié un projet nommé eventlet-pyqt . J'espère que cela pourrait être utile pour celui qui veut utiliser Greenlet dans leur application PyQt. J'ai aussi essayé gevent, mais il était difficile pour moi d'écrire un plugin pour libevent à cause de ma mauvaise expérience en langage C. Le principal problème en utilisant QApplicaton::processEvents()
ou un QTimer
zéro intervalle est, le programme de fonctionner en boucle infinie, provoque l'utilisation du noyau de CPU à 100%. Pour éviter cela, je l'ai écrit un nouveau centre pour remplacer la fonction select()
avec QSocketNotifier
PyQt. Espérons que ce message pourrait aider quelqu'un.