[Stackless] Stackless + PyQt example
Carlos Eduardo de Paula
carlosedp at gmail.com
Fri Mar 2 22:51:03 CET 2007
Hi guys,
Some time ago I created a small producer-consumer application
integrated with PyQt.
The application uses no threads, all is done by tasklets, simple but i
think the example is valid and can be extended.
The next example i will create a producer-consumer with the queue as a
separate process all comunicating using Twisted perspective broker
over a TCP connection. I will create one with a PyQt interface and one
with text output.
Richard, if you think the example is ok, it can be added to the wiki
or the sandbox.
The example is composed of two files, one is the interface made with
Qt Designer that is imported by the main one. The other is the
application itself.
Best regards,
Carlos
-------------- next part --------------
import stackless
import time
import random
import sys
from PyQt4 import QtGui, QtCore
# Nice way to put the tasklet to sleep - from stackless.com wiki/Idioms
##########################################################
sleepingTasklets = []
def Sleep(secondsToWait):
channel = stackless.channel()
endTime = time.time() + secondsToWait
sleepingTasklets.append((endTime, channel))
sleepingTasklets.sort()
# Block until we get sent an awakening notification.
channel.receive()
def ManageSleepingTasklets():
while 1:
if len(sleepingTasklets):
endTime = sleepingTasklets[0][0]
if endTime <= time.time():
channel = sleepingTasklets[0][1]
del sleepingTasklets[0]
# We have to send something, but it doesn't matter what as it is not used.
channel.send(None)
# if len(sleepingTasklets) <= 0: time.sleep(endTime-time.time())
#time.sleep(0.001)
stackless.schedule()
if len(sleepingTasklets) <= 0: stackless.getcurrent().kill()
#stackless.tasklet(ManageSleepingTasklets)()
##########################################################
class Agent(object):
def __init__(self, name=None):
self.ch = stackless.channel()
self.name = name
self.items = 0
self.kill = False
self.t = stackless.tasklet(self.runAction)()
def runAction(self):
while not self.kill:
self.action()
def action(self):
pass
class Queue(object):
def __init__(self, name):
self.queue_start=0
self.qt = self.queue_start
self.max_size = 100
self.running = False
self.kill = False
self.produced = 0
self.consumed = 0
self.q_empty = 0
self.q_full = 0
self.producers = []
self.consumers = []
def put(self, qty=1, who=None):
if self.qt+qty < self.max_size:
self.qt += qty
self.produced += 1
else:
self.q_full += 1
def get(self, qty=1, who=None):
if self.qt >= qty:
self.qt -= qty
self.consumed += 1
else:
self.q_empty += 1
class Producer(Agent):
def __init__(self,name, queue):
Agent.__init__(self, name)
self.time = random.random()
self.items = 0
self.queue = queue
self.queue.producers.append(self)
def action(self):
while self.queue.running:
if self.queue.qt < 5:
Sleep(self.time)
else:
Sleep(self.time*2)
self.queue.put(1, self.name)
self.items += 1
else:
Sleep(self.time)
class Consumer(Agent):
def __init__(self, name, queue):
Agent.__init__(self, name)
self.time = random.random()
self.queue = queue
self.queue.consumers.append(self)
def action(self):
while self.queue.running:
self.queue.get(1, self.name)
self.items += 1
if self.queue.qt < 5:
Sleep(self.time*2)
else:
Sleep(self.time)
else:
Sleep(self.time)
##########################################################################
class mainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
from prodcon_ui import Ui_MainWindow
# Set up the user interface from Designer.
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.connect(self.ui.start, QtCore.SIGNAL("clicked()"),self.start) # <- Button
self.connect(self.ui.stop, QtCore.SIGNAL("clicked()"),self.stop) # <- Button
self.connect(self.ui.add, QtCore.SIGNAL("clicked()"),self.addtoqueue) # <- Button
self.connect(self.ui.addprod, QtCore.SIGNAL("clicked()"),self.addprod) # <- Button
self.connect(self.ui.addcons, QtCore.SIGNAL("clicked()"),self.addcons) # <- Button
self.started = False
self.killtasks = False
self.q = Queue("Queue")
self.PID = 0
self.CID = 0
def closeEvent(self, event):
self.killtasks = True
try:
for p in self.q.producers:
p.kill = True
for c in self.q.consumers:
c.kill = True
self.sleepMan.kill()
self.showReport()
except: pass
def start(self):
if self.started:
self.q.running = True
self.ui.statusbar.showMessage("Running")
return
self.ui.statusbar.showMessage("Starting up...")
self.started = True
self.q.running = True
self.sleepMan = stackless.tasklet(ManageSleepingTasklets)()
self.monit = stackless.tasklet(self.monitor)()
self.ui.queue.setMaximum(self.q.max_size)
for i in range(num_prod):
self.addprod()
for i in range(num_cons):
self.addcons()
self.ui.statusbar.showMessage("Running")
stackless.run()
def stop(self):
self.q.running = False
self.ui.statusbar.showMessage("Stopped")
def addprod(self):
ID = self.PID
name = "P"+str(ID)
a = Producer(name, self.q)
self.PID += 1
def addcons(self):
ID = self.CID
name = "C"+str(ID)
a = Consumer(name, self.q)
self.CID += 1
def addtoqueue(self):
self.q.qt += 10
def monitor(self):
while not self.killtasks:
QtGui.QApplication.processEvents()
self.ui.queue.setValue(self.q.qt)
self.ui.prod.setText(str(len(self.q.producers)))
self.ui.cons.setText(str(len(self.q.consumers)))
Sleep(0.033)
#stackless.schedule()
def showReport(self):
print
print "--------------------------"
for p in self.q.producers:
print "Producer", p.name , "produced: ", p.items, "items. Each production took: ", p.time
print
for c in self.q.consumers:
print "Consumer", c.name , "consumed: ", c.items, "items. Each consuption took: ", c.time
print "--------------------------"
print "Produced units: ", self.q.produced
print "Consumed units: ", self.q.consumed
print "Left in queue: ", self.q.qt
print
print "Queue became zero ", self.q.q_empty, " times."
print "Queue became full ", self.q.q_full, " times."
print
print "--------------------------"
###########################################################
num_prod = 10 # Number of starting producers
num_cons = 10 # Number of starting consumers
def main(args):
app = QtGui.QApplication(sys.argv)
mainwindow = mainWindow()
mainwindow.show()
sys.exit(app.exec_())
if __name__=="__main__":
main(sys.argv)
-------------- next part --------------
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'prodcon_ui.ui'
#
# Created: Tue Aug 29 15:41:04 2006
# by: PyQt4 UI code generator 4-snapshot-20060814
#
# WARNING! All changes made in this file will be lost!
import sys
from PyQt4 import QtCore, QtGui
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(QtCore.QSize(QtCore.QRect(0,0,392,351).size()).expandedTo(MainWindow.minimumSizeHint()))
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.cons = QtGui.QLineEdit(self.centralwidget)
self.cons.setGeometry(QtCore.QRect(80,170,31,20))
self.cons.setObjectName("cons")
self.stop = QtGui.QPushButton(self.centralwidget)
self.stop.setGeometry(QtCore.QRect(60,70,75,23))
self.stop.setObjectName("stop")
self.start = QtGui.QPushButton(self.centralwidget)
self.start.setGeometry(QtCore.QRect(60,40,75,23))
self.start.setObjectName("start")
self.addprod = QtGui.QPushButton(self.centralwidget)
self.addprod.setGeometry(QtCore.QRect(270,160,75,23))
self.addprod.setObjectName("addprod")
self.label = QtGui.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(20,150,48,14))
self.label.setObjectName("label")
self.prod = QtGui.QLineEdit(self.centralwidget)
self.prod.setGeometry(QtCore.QRect(80,150,31,20))
self.prod.setObjectName("prod")
self.addcons = QtGui.QPushButton(self.centralwidget)
self.addcons.setGeometry(QtCore.QRect(270,130,75,23))
self.addcons.setObjectName("addcons")
self.label_2 = QtGui.QLabel(self.centralwidget)
self.label_2.setGeometry(QtCore.QRect(20,171,53,14))
self.label_2.setObjectName("label_2")
self.add = QtGui.QPushButton(self.centralwidget)
self.add.setGeometry(QtCore.QRect(270,40,75,23))
self.add.setObjectName("add")
self.lcdNumber = QtGui.QLCDNumber(self.centralwidget)
self.lcdNumber.setGeometry(QtCore.QRect(170,40,64,23))
self.lcdNumber.setObjectName("lcdNumber")
self.queue = QtGui.QProgressBar(self.centralwidget)
self.queue.setGeometry(QtCore.QRect(190,80,22,211))
self.queue.setMaximum(60)
self.queue.setProperty("value",QtCore.QVariant(0))
self.queue.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
self.queue.setOrientation(QtCore.Qt.Vertical)
self.queue.setInvertedAppearance(False)
self.queue.setTextDirection(QtGui.QProgressBar.TopToBottom)
self.queue.setObjectName("queue")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0,0,392,21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QObject.connect(self.queue,QtCore.SIGNAL("valueChanged(int)"),self.lcdNumber.display)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
self.stop.setText(QtGui.QApplication.translate("MainWindow", "Stop", None, QtGui.QApplication.UnicodeUTF8))
self.start.setText(QtGui.QApplication.translate("MainWindow", "Start", None, QtGui.QApplication.UnicodeUTF8))
self.addprod.setText(QtGui.QApplication.translate("MainWindow", "+ Prod", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("MainWindow", "Producers", None, QtGui.QApplication.UnicodeUTF8))
self.addcons.setText(QtGui.QApplication.translate("MainWindow", "+ Cons", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setText(QtGui.QApplication.translate("MainWindow", "Consumers", None, QtGui.QApplication.UnicodeUTF8))
self.add.setText(QtGui.QApplication.translate("MainWindow", "+10", None, QtGui.QApplication.UnicodeUTF8))
-------------- next part --------------
_______________________________________________
Stackless mailing list
Stackless at stackless.com
http://www.stackless.com/mailman/listinfo/stackless
More information about the Stackless
mailing list