首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > perl python >

一个小聊天室的代码运行总是报错解决思路

2013-01-25 
一个小聊天室的代码运行总是报错# codinggbkCreated on 2012-5-22@author: dengjianfrom asyncore

一个小聊天室的代码运行总是报错


# coding=gbk
'''
Created on 2012-5-22

@author: dengjian
'''
from asyncore import dispatcher
from asynchat import async_chat
import socket,asyncore

PORT= 5005
NAME='TestChat'

class EndSession(Exception): pass

class CommandHandler:
    """
    类似于标准库cmd.Cmd的简单命令处理程序。
    """
    
    def unknown(self,session,cmd):
        #'响应未知命令'
        session.push('Unknown command: %s\r\n' % cmd)
        
    def handle(self,session,line):
        #'处理从给定的会话中接收到的行'
        if not line.strip(): return
        #分离命令
        parts=line.split(' ',1)
        cmd=parts[0]
        try : line=parts[1].strip()
        except IndexError: line=''
        #试着查找处理程序:
        meth=getattr(self,'do_'+cmd,None)
        try:
            #假如它是可调用的
            meth(session,line)
        except TypeError:
            # 如果不可以被调用,此段代码响应未知的命令:
            self.unknown(session,cmd)
            
class Room(CommandHandler):
    """
    包括一个或多个用户(会话)的泛型环境。它负责基本的命令处理和广播。
    """
    def __init__(self,server):
        self.server=server
        self.sessions=[]
        
    def add(self,session):
        #'一个会话(用户)已进入房间'
        self.sessions.append(session)
        
    def remove(self,session):
        #'一个会话(用户)已离开房间'
        self.sessions.remove(session)
        
    def broadcast(self,line):
        #'向房间中的所有会话发送一行'
        for session in self.sessions:
            session.push(line)
            
    def do_logout(self,session,line):
        #'响应logout命令'
        raise EndSession
    
class LoginRoom(Room):
    """
    为刚刚连接上的用户准备的房间。
    """
    def add(self,session):


        Room.add(self, session)
        #当用户进入时,问题他或她:
        self.broadcast('welcome to %s\r\n' % self.server.name)
        
    def unknown(self,session,cmd):
        #所有未知命令(除了login或者logout外一切)
        #会导致一个警告
        session.push('Please log in \n Use "login <nick> "\r\n')
        
    def do_login(self,session,line):
        name=line.strip()
        #确保用户输入了名字
        if not name:
            session.push('Please enter a name\r\n')
        #确保用户名没有被利用:
        elif name in self.server.users:
            session.push('The name "%s" is taken.\r\n' % name)
            session.push('Please try again.\r\n')
        else:
            #名字没问题,所以存储在会话中,并且
            #将用户移动到主聊天室。
            session.name=name
            session.enter(self.server.main_room)
            
class ChatRoom(Room):
    """
    为多用户相互聊天准备的房间
    """
    
    def add(self,session):
        #告诉所有人有新用户进入
        self.broadcast(session.name + 'has entered the room.\r\n')
        self.server.users[session.name]=session
        Room.add(self.session)
        
    def remove(self,session):
        Room.remove(self, session)
        #告诉所有人有用户离开:
        self.broadcast(session.name + 'has left the room.\r\n')
        
    def do_say(self,session,line):
        self.broadcast(session.name + ': ' +line+'\r\n')
        
    def do_look(self,session,line):
        #'处理look命令,该命令用于查看谁在房间内'
        session.push('The following are in this room:\r\n')
        for other in self.sessions:
            session.push(other.name + '\r\n')
            
    def do_who(self,session,line):


        #'处理who命令,该命令用于查看谁登录了'
        session.push('The following are logged in:\r\n')
        for name in self.server.users:
            session.push(name + '\r\n')
            
class LogoutRoom(Room):
    """
    为单用户准备的简单房间,只用于将用户名从服务器移除。
    """
    def add(self,session):
        #当会话(用户)进入要删除的logoutRomm时
        try: del self.server.users[session.name]
        except KeyError: pass
        
class ChatSession(async_chat):
    """
    单会话,负责和单用户通信
    """
    def __init__(self,server,sock):
        async_chat.__init__(self, sock)
        self.server=server
        self.set_terminator("\r\n")
        self.data=[]
        self.name=None
        #所有的会话都开始于单独的LoginRoom中:
        self.enter(LoginRoom(server))
        
    def enter(self,room):
        #从当前房间移除自身(self),并且将自身添加到
        #下一个房间
        try: cur=self.room
        except AttributeError: pass
        else: cur.remove(self)
        self.room=room
        room.add(self)
        
    def collect_incoming_data(self,data):
        self.data.append(data)
        
        
    def found_terminator(self):
        line=''.join(self.data)
        self.data=[]
        try: self.room.handle(self,line)
        except EndSession:
            self.handle_close()
            
    def handle_close(self):
        async_chat.handle_close(self)
        self.enter(LogoutRoom(self.server))
        
class ChatServer(dispatcher):
    """
    只有一个房间的聊天服务器。
    """
    def __init__(self,port,name):
        dispatcher.__init__(self)
        self.create_socket(socket.AF_INET,socket.SOCK_STREAM)
        self.set_reuse_addr()
        self.bind(('',port))


        self.listen(5)
        self.name=name
        self.users={}
        self.main_room=ChatRoom(self)
        
    def handle_accept(self):
        conn, addr=self.accept()
        ChatSession(self,conn)
        
if __name__=='__main__':
    s = ChatServer(PORT,NAME)
    try: asyncore.loop()
    except KeyboardInterrupt: print



刚运行时不会报错,但是输入:login 用户名,就会有以下的错误

Traceback (most recent call last):
  File "/home/dengjian/workspace/code24/chatserver.py", line 193, in <module>
    try: asyncore.loop()
  File "/usr/lib/python2.7/asyncore.py", line 210, in loop
error: uncaptured python exception, closing channel <__main__.ChatSession connected 127.0.0.1:37790 at 0xb707ecec> (<type 'exceptions.AttributeError'>:ChatRoom instance has no attribute 'session' [/usr/lib/python2.7/asyncore.py|read|79] [/usr/lib/python2.7/asyncore.py|handle_read_event|438] [/usr/lib/python2.7/asynchat.py|handle_read|158] [/home/dengjian/workspace/code24/chatserver.py|found_terminator|165] [/home/dengjian/workspace/code24/chatserver.py|handle|37] [/home/dengjian/workspace/code24/chatserver.py|do_login|94] [/home/dengjian/workspace/code24/chatserver.py|enter|156] [/home/dengjian/workspace/code24/chatserver.py|add|105])
    poll_fun(timeout, map)
  File "/usr/lib/python2.7/asyncore.py", line 151, in poll
    read(obj)
  File "/usr/lib/python2.7/asyncore.py", line 83, in read
    obj.handle_error()
  File "/usr/lib/python2.7/asyncore.py", line 495, in handle_error
    self.handle_close()
  File "/home/dengjian/workspace/code24/chatserver.py", line 171, in handle_close
    self.enter(LogoutRoom(self.server))
  File "/home/dengjian/workspace/code24/chatserver.py", line 154, in enter
    else: cur.remove(self)
  File "/home/dengjian/workspace/code24/chatserver.py", line 108, in remove
    Room.remove(self, session)
  File "/home/dengjian/workspace/code24/chatserver.py", line 56, in remove
    self.sessions.remove(session)
ValueError: list.remove(x): x not in list

查了几天了,都没有找到问题,求大牛帮助
[解决办法]
引用:
File "/home/dengjian/workspace/code24/chatserver.py", line 154, in enter
  else: cur.remove(self)
  File "/home/dengjian/workspace/code24/chatserver.py", line 108, in remove
  Room.remove(self, session)
  File "/home/dengjian/workspace/code24/chatserver.py", line 56, in remove
  self.sessions.remove(session)
ValueError: list.remove(x): x not in list



错误信息说的很清楚:
enter函数中调用了: cur.remove(self),进而调用了Room.remove,最后调用了self.session.remove.但是刚开始是,该用户并不在当前房间中。所以remove出错了。remove之前要先检查用户是否在self.session中。
[解决办法]
呵呵,不好意思,看错啦,刚睡醒...

热点排行