问题描述:

I am doing Cesare Rocchi's tutorial "How To Create A Socket Based iPhone App and Server" http://www.raywenderlich.com/3932/how-to-create-a-socket-based-iphone-app-and-server#comments

Do I need to define an attribute called 'name' in the "class IphoneChat(Protocol)" or is it inherited from "twisted.internet.protocol?" If it is inherited, how do I access it correctly?

server.py:

from twisted.internet.protocol import Factory, Protocol

from twisted.internet import reactor

class IphoneChat(Protocol):

def connectionMade(self):

self.factory.clients.append(self)

print "clients are", self.factory.clients

def connectionLost(self, reason):

self.factory.clients.remove(self)

def dataReceived(self, data):

a = data.split(':')

print a

if len(a) > 1:

command = a[0]

content = a[1]

msg = ""

if command == "iam":

self.name = content

msg = self.name + "has joined"

elif command == "msg":

msg = self.name + ": " + content

print msg

for c in self.factory.clients:

c.message(msg)

def message(self, message):

self.transport.write(message + '\n')

factory = Factory()

factory.protocol = IphoneChat

factory.clients = []

reactor.listenTCP(80, factory)

print "Iphone Chat server started"

reactor.run()

Terminal output:

Iphone Chat server started

...

--- <exception caught here> ---

File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/twisted/internet/selectreactor.py", line 150, in _doReadOrWrite

why = getattr(selectable, method)()

File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/twisted/internet/tcp.py", line 199, in doRead

rval = self.protocol.dataReceived(data)

File "server.py", line 30, in dataReceived

msg = self.name + ": " + content

exceptions.AttributeError: IphoneChat instance has no attribute 'name'

Problem solving steps so far:

  • I read that "name" is managed server side, in the self.factory.clients list, but then I looked for a class definition of twisted.internet.protocol and found nothing like "name" http://twistedmatrix.com/documents/11.0.0/api/twisted.internet.protocol.Protocol.html
  • From what I have read elsewhere this could just be an indentation error.

网友答案:

Well the error is quite logical

if command == "iam":
    self.name = content
    msg = self.name + "has joined"
elif command == "msg":
    msg = self.name + ": " + content 
    print msg

In the first if clause you assign a value to self.name which may either rely on assumption that self.name exists somewhere, or on assumption that it is new and needs to be declared, but in elif you seem to assume with certainty that self.name already exists, it turns out it doesn't so you get an error.

I guess your safest option consists of simply adding self.name at the beginning of dataReceived method:

def dataReceived(self, data):
    self.name = ""

this will get rid of the error. As an alternative you could also add self.name to init method of IphoneChat.If you need self.name in other functions not only in dataReceived then adding init with self.name is the way to go, but from your code it seems you only need it in datareceived so just add it there. Adding self.name in init would look like this:

class IphoneChat(Protocol):
    def __init__(self):
        self.name = ""

or you can also simply do

class IphoneChat(Protocol):
    name = ""

and then go on with name instead of self.name.

网友答案:

You may be parsing the wrong text.

The article says to type “aim:cesare” and then "msg:hi" but your program doesn't know how to handle "aim:" as a command. So when you run "msg:hi" afterwards, self.name would not have a value. It looks like it was a typo from the article's author. The following commands should work:

"aim:cesare"

=> cesare

     has joined

"msg:hi"

=> cesare

   : hi
相关阅读:
Top