[Twisted-Python] Question about writing a server that accepts multiple clients with independent processing

Phil Mayers p.mayers at imperial.ac.uk
Thu Feb 21 09:52:19 EST 2008


>> You didn't by any chance use a class variable did you e.g.:
>>
>> class foo(...):
>>   my_data = []
>>   def dataReceived(self, data):
>>     self.my_data.append(data)
>>
> Yes, that must be it :
> 
>    class XmlStreamTestSrv(xmlstream.XmlStream):
> 
>        def __init__(self):
>            xmlstream.XmlStream.__init__(self)
>            self.message = []

No, this is fine, as you say setting "self.foo" creates an instance 
variable.

I personally don't use __init__ methods of the protocol because I 
believe some protocols make complex use of this, but it should be fine.

>    ...
> 
> even though I though that in python if you put a "self." in front it was 
> an instance variable and not a class variable. I have been also having 
> some strange problems, like if I overload
> 
>    def connectionMade(self):
> 
> it never gets called, even though the parent class (XmlStream) also has 
> it, and also I can't call self.transport.getPeer() or 
> xmlstream.XmlStream.transport.getPeer(), I get :
> 
>    print 'Connection from %s!' % 
> str(xmlstream.XmlStream.transport.getPeer())
>    exceptions.AttributeError: 'NoneType' object has no attribute 'getPeer'
> 
> so maybe something is wrong somewhere.

It sounds like the protocol isn't being hooked up to the transport.

>> ...is wrong. "my_data" is shared by all instances of the class and is 
>> mutable. You'll need to create instance variables, usually (I believe) 
>> as part of the factory process.
> Ok, I'll look into that, thanks.
>>
>> If you can write a minimal example showing the problem, someone can 
>> probably tell you what you're doing wrong.
>>
> Ok, thanks, here's a minimal example :
> 
>    from twisted.words.xish import xmlstream, domish
>    from twisted.internet import reactor, protocol
>    from twisted.internet.protocol import Protocol, Factory
>    from twisted.words.xish import xpath
> 
> 
>    class XmlStreamTestSrv(xmlstream.XmlStream):
> 
>        def __init__(self):
>            xmlstream.XmlStream.__init__(self)
>            self.message = []
> 
>        def connectionMade(self): # never called, why?
>            print 'Connected :' #, string(self.transport.getPeer().host)
> 
>        def _onHeader(self, element):
>            #print "got header from % : %s" % 
> (str(self.transport.getPeer().host), element.toXml())
>            self.message.append(element.toXml())
> 
>        def _connected(self, xs):
>            #print 'Connection from %s!' % 
> str(xmlstream.XmlStream.transport.getPeer().host)
>            xs.addObserver("/header", self._onHeader)
> 
>    if __name__ == "__main__":
> 
>        c = XmlStreamTestSrv()
> 
>        f = xmlstream.XmlStreamFactory()
>        #f.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT, c._connected)
>        f.addBootstrap(xmlstream.STREAM_START_EVENT, c._connected)
> 
>        reactor.listenTCP(4321, f)
>        reactor.run()

Ah - you need to set the "protocol" attribute on the factory to the 
protocol *class*, and then when a connection is made the class will be 
instantiated and connected to the transport. This is why self.transport 
is None, and because you're using an instance of the protocol, the data 
is getting squashed together. Do this:

f = xmlstream.XmlStreamFactory()
f.protocol = XmlStreamTestSrv
reactor.listenTCP(4321, f)
reactor.run()





More information about the Twisted-Python mailing list