[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