Domanda

Qualcuno utilizzato PyQt con gevent? Come collegare PyQt ciclo per il gevent?

http://www.gevent.org/ - libreria di rete Python coroutine-based che utilizza Greenlet a fornire un API sincrono alto livello sulla parte superiore del ciclo di eventi libevent.

È stato utile?

Soluzione

Ecco come si dovrebbe cambiare PyQt da session1 di esempio per collaborare: https: // github.com/traviscline/pyqt-by-example/commit/b5d6c61daaa4d2321efe89679b1687e85892460a

Altri suggerimenti

È possibile utilizzare un IDLE Qt "timer" per consentire gevent per l'elaborazione dei suoi microspire mentre eventi Qt trattati per un breve periodo di tempo, per esempio 10 millisecondi. Non è ancora perfetto, dal momento che non dà la "liscia" possibile integrazione. E 'perché non usiamo un ciclo singolo evento sia per Qt e gevent, solo "interleaving" in tempo.

La soluzione corretta sarebbe quella di consentire libevent per l'ascolto su nuovi eventi Qt in qualche modo, ma non sono stato in grado di capire come fare in pratica ancora. Forse avere Qt per inviare qualcosa da gevent tramite una presa di corrente quando un evento GUI arriva in caso di coda avrebbe aiutato. Qualcuno ha risolto questo?

Esempio di funzionamento:

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

Ho provato il seguente approccio: per avere un "PyQt backend" per gevent, vale a dire. un'implementazione del gevent realizzazione ciclo uso di costrutti PyQt come QSocketNotifier, QTimer, ecc invece del ciclo libev. Finalmente ho trovato molto più facile che fare il contrario, e prestazioni sono molto buone (anello di Qt si basa sulla glib sotto Linux, non è poi così male).

Ecco il link al progetto su GitHub per chi è interessato: https://github.com/mguijarr/qtgevent

Questo è solo l'inizio, ma funziona bene per le prove che ho fatto. Sarei felice se la gente con più esperienza con gevent e PyQt potrebbero contribuire.

si Sould evitare l'uso app.exec_ (), si tratta di una funzione di loop che utilizzano questa funzione per gli eventi del processo:

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

in modo da poter chiamare direttamente processEvents.

ho pubblicato un progetto denominato eventlet-PyQt . Spero che possa essere utile per chi desidera utilizzare greenlet nella loro applicazione PyQt. Ho anche provato gevent, ma era difficile per me scrivere un plugin per libevent a causa della mia scarsa esperienza linguaggio C. Il principale problema utilizzando QApplicaton::processEvents() o un QTimer zero intervallo è, il programma eseguito in loop infinito, provoca 100% utilizzo CPU core. Per evitare questo, ho scritto un nuovo hub per sostituire la funzione select() con QSocketNotifier di PyQt. Spero che questo messaggio potrebbe aiutare qualcuno.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top