[Twisted-Python] anyway to get data from a protocol instance?

Jean-Paul Calderone exarkun at divmod.com
Wed Aug 9 10:43:33 EDT 2006


On Wed, 9 Aug 2006 14:19:09 +0200, Torsten Irländer <feldmatrix at gmx.de> wrote:
>On Wed, Aug 09, 2006 at 04:43:19PM +0800, wang wei wrote:
>> please have a look of fellow code.
>>
>> from twisted.internet import reactor, protocol
>>
>> class echo(protocol.Protocol):
>>    def __init__(self):
>>        from Queue import Queue
>>        self.q = Queue()
>>
>>    def lineReceived(self, line):
>>        self.q.put(line)
>>
>> class echofactory(protocol.ServerFactory):
>>
>>    def buildProtocol(self, addr):
>>        p = echo()
>>        p.factory = self
>>        return p
>>
>> class runEcho:
>>    def __init__(self):
>>        a = echofactory()
>>        reactor.listenTCP(1024, a)
>>        reactor.run()
>>
>>
>> My question is how can I get size of Queue q from another class when the
>> program running.

I suspect you are perfectly aware of how to get the size of the Queue and
that your actual problem is getting a reference to the protocol instance.

The answer here has little to do with Twisted specifically.  You just need
to organize your code such that the reference is available where it is
needed.

>
>That is a question I'm also interested in a good answer. My proposal would be
>to return the protocol object as a deferred. For me this works, but I'm not
>sure if this is a good approach. I extended wang wei's code so that the
>protocol data can be accessed by other classes.

This is a perfectly serviceable solution, although it may be more complex
than is strictly necessary.

>
>from twisted.internet import reactor, protocol, defer
>
>class echo(protocol.Protocol):
>    def __init__(self):
>        from Queue import Queue
>        self.q = Queue()
>
>    def connectionMade(self):
>        self.factory.deferred.callback(self)
>
>    def lineReceived(self, line):
>        print line
>        self.q.put(line)
>
>class echofactory(protocol.ServerFactory):
>
>    def __init__(self):
>        self.deferred = defer.Deferred()
>
>    def buildProtocol(self, addr):
>        p = echo()
>        p.factory = self
>        return p
>
>class runEcho:
>    def connect(self):
>        a = echofactory()
>        a.deferred.addCallback(self.set_myprotocol)
>        reactor.listenTCP(1024, a)
>        reactor.run()
>
>    def set_myprotocol(self,proto):
>        print "protocol ready!"
>        self.proto = proto
>        print self.proto.q
>
>r = runEcho()
>r.connect()
>
>
>Can anyone give some comments on this? I am at the very beginning
>of twisted programming and I'm not sure if this is a good way to
>access the protocol class from the outside.

For a single connection, twisted.internet.protocols.ClientCreator performs
approximately the same task.  For multiple connections, you may want to
eliminate the Deferred entirely and simply call a method with a well-known
name.  For example:

    def connectionMade(self):
        self.factory.setMyProtocol(self)

Or, to handle multiple simultaneous connections:

    def connectionMade(self):
        self.factory.addProtocol(self)


    def connectionLost(self, reason):
        self.factory.removeProtocol(self)

There is an implementation of this tracking pattern in Twisted already,
in fact.  Take a look at twisted.protocols.policies.WrappingFactory, which
keeps a dictionary of protocol instances, updating it whenever a new
connection is made or an old one lost.

Jean-Paul




More information about the Twisted-Python mailing list