[Twisted-Python] a tranceiver interface

Clark C. Evans cce at clarkevans.com
Thu May 29 01:50:30 EDT 2003


There are two forms of data flow constructs available, push and pull.  
The "push" based consumer/producer flow looks something like...

    class receiver:
        """ what is a consumer """
        def start(self):
            'what is called to start the stream'
        def result(self, value):
            'what is called for each data item in the stream'
        def finish(self):
            'what is called at the end of the stream'

    class transmitter:
        """ what is a producer """
        def __init__(self, receiver):
            self.receiver = consumer
            # push data to receiver when ready

    class tranceiver(receiver, transmitter):
        """ what is both a producer and a consumer
            by default, just be a simple 'passthrough'
        """
        def start(self):
            self.receiver.start()
        def result(self, value):
            # process result
            self.receiver.result(value)
        def finish(self):
            self.receiver.finish()
    
The equivalent version of a 'passthrough' tranceiver in "pull" land 
can be written nicely as a generator:
 
    def consumer(producer):
        # start: what is called to start the stream
        for result in producer:
            # what is called for each data item in the stream
            yield result
        # finish: what is called at the end of the stream

What is intersting is that the producer is passed the consumer (not the 
other way around) as the 'push' example, and that the 3 states are 
encapsulated not by a particular callback function, but more by the 
position within the generator.  Unfortunately, direct use of generator 
like this doesn't give other operations a chance to process, but this 
shortcoming can be addressed by using the flow module:

    def consumer(producer):
        # start: what is called to start the stream
        producer = flow.wrap(producer)
        yield producer
        for result in producer:
            # what is called for each data item in the stream
            yield result
            yield producer
        # finish: what is called at the end of the stream

In this way, the consumer works exactly as it did before, only
that now other operations can proceed (if the producer is not
immediately ready) when "yield producer" is encountered.

Best,

Clark




More information about the Twisted-Python mailing list