是否有人使用PyQt与gevent? 如何将PyQt循环链接到gevent?
http://www.gevent.org/ - 基于协程的Python网络库,它使用greenlet在libevent事件循环之上提供高级同步API。
答案 0 :(得分:4)
您可以使用Qt IDLE"计时器"允许gevent
处理其微线程,而短时间内没有处理Qt事件,例如10毫秒。它仍然不完美,因为它没有给出最平稳的"可能的整合。这是因为我们没有为Qt和gevent使用单个事件循环,只是"交错"他们及时。
正确的解决方案是允许libevent以某种方式听取新的Qt事件,但我还没有能够在实践中弄清楚如何做到这一点。当GUI事件到达事件队列时,可能让Qt通过套接字向gevent发送内容会有所帮助。有人解决了吗?
工作示例:
""" 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 :(得分:3)
我尝试了以下方法:为gevent设置一个“PyQt后端”,即。使用PyQt构造(如QSocketNotifier,QTimer等)而不是libev循环的gevent循环的实现。最后我发现它比反过来容易得多,而且性能非常好(Qt的循环基于Linux下的glib,它并不是那么糟糕)。
以下是github上项目的链接: https://github.com/mguijarr/qtgevent
这只是一个开始,但它适用于我所做的测试。如果对gevent和PyQt有更多经验的人可以做出贡献,我会很高兴。
答案 2 :(得分:2)
以下是如何通过示例的session1更改pyqt以进行合作:https://github.com/traviscline/pyqt-by-example/commit/b5d6c61daaa4d2321efe89679b1687e85892460a
答案 3 :(得分:1)
你应该避免使用app.exec_(),它是一个循环函数,它使用这个函数来处理事件:
http://doc.qt.nokia.com/stable/qcoreapplication.html#processEvents
所以你可以直接调用processEvents。
答案 4 :(得分:1)
我发布了一个名为eventlet-pyqt的项目。我希望它对那些想在PyQt应用程序中使用greenlet的人有用。我也试过gevent,但由于我糟糕的C语言经验,我很难为libevent写一个插件。使用QApplicaton::processEvents()
或零间隔QTimer
的主要问题是,程序进入无限循环,导致100%的CPU核心使用率。为了避免这种情况,我编写了一个新的集线器,用PyQt的select()
替换QSocketNotifier
函数。希望这条消息可以帮助一些人。