Generators are great if you ask me and so are the power ups that Python 2.5 adds to them. Since the last version of Python you have:
- yield as an expression so you can store a returned value
- values can be sent to the generator with gen.send(value), so you can somewhat handle the generator from the outside easily
- exceptions can be raised inside the generator from the outside with gen.throw()
- the generation process can be stopped anytime with gen.close()
This way Python 2.3 simple generators turn into full fledged coroutines.
Recently a library called multitask appeared on PyPi index. With multitask you can do cooperative multitasking and async I/O only with bare generators.
So fifteen minutes later I rewrote the classic producer/consumer example with it.
The source code is not really different from the generators only example I demoed last month:
[code lang="python"] import multitask
class Producer(object):
removed for brevity
class Consumer(object): def init(self, buffer, name): self.buffer = buffer self.name = name
def run(self): while not self.buffer.empty():
task will be resumed after an element is available in the queue
data = (yield self.buffer.get()) print “%s has got %s from the buffer.” % (self.name, data)
the task will be resumed after 1.5 seconds
yield multitask.sleep(1.5) print “%s is doing something with %s” % (self.name, data)
def main(): buffer = multitask.Queue() prod = Producer(buffer, “Producer”) cons = Consumer(buffer, “Consumer”)
multitask.add(prod.run()) multitask.add(cons.run()) multitask.run() [/code]
This time, anyway, the scheduler is provided by multitask which basically iterates on the tasks and sends in the values getting the outputs. Generators can make your code really simple
Here’s the full example: prodcons_multitask.py

