2014-07-24 12 views
17

Python2'yi python3'e dönüştürmeye çalışıyorum , bir hatam var: programı bağlamak için "telnet localhost 5005" komutunu kullanın, ancak oturum açmaya çalıştığımda bir sorun var rapor edildi.python3 Type str arabelleği desteklemiyor API

ScreenShot:

Kodlar:

#!/usr/bin/env python3 
__author__ = 'tcstory' 
from asyncore import dispatcher 
from asynchat import async_chat 
import socket, asyncore 

PORT=5005 
NAME='TestChat' 

class EndSession(Exception): pass 

class CommandHandler: 
    ''' 
    Simple command handler similar to cmd.Cmd from the standard library 
    ''' 

    def unknown(self, session, cmd): 
     'Respond to an unknown command' 
     session.push('Unkonw command: {0}\r\n'.format(cmd).encode()) 

    def handle(self, session, line): 
     'Handle a received line from a given session' 
     if not line.strip(): 
      return 
     #Split off the command 
     parts = line.split(' ', 1) 
     cmd = parts[0] 
     try: 
      line=parts[1].strip() 
     except IndexError: 
      line='' 
     #Try to find a handler 
     meth=getattr(self,'do_'+cmd,None) 
     try: 
      #Assume it's callable 
      meth(session,line) 
     except TypeError: 
      #If it isn't ,respond to the unknown command 
      self.unknown(session,cmd) 

class Room(CommandHandler): 
    ''' 
    A generic environment that may contain one or more users(sessions).it takes care of basic command handling and broadcasting. 
    ''' 
    def __init__(self,server): 
     self.server=server 
     self.sessions=[] 

    def add(self,session): 
     'A session(user) has entered the room' 
     self.sessions.append(session) 

    def remove(self,session): 
     'A session (user) has left the room' 
     self.sessions.remove(session) 

    def broadcast(self,line): 
     'Send a line to all sessions in the room' 
     for session in self.sessions: 
      session.push(line.encode()) 

    def do_logout(self,session,line): 
     'Respond to the logout command' 
     raise EndSession 

class LoginRoom(Room): 
    ''' 
    A room meant for a single person who has just connected 
    ''' 

    def add(self,session): 
     Room.add(self,session) 
     #When a user enters,greet him/her 
     self.broadcast('Welcome to {0}\r\n'.format(self.server.name)) 

    def unknown(self, session, cmd): 
     #All unknown commands (anything except login or logout) 
     #results in a prodding 
     session.push('Please log in\nUse "login <nick>"\r\n'.encode()) 

    def do_login(self,session,line): 
     name=line.strip() 
     #Make sure the user has entered a name 
     if not name: 
      session.push('Please enter a name\r\n'.encode()) 
     #Make sure that the name isn't in use 
     elif name in self.server.users: 
      session.push('The name {0} is taken.\r\n'.format(name).encode()) 
      session.push('Please try again.\r\n'.encode()) 
     else: 
      #The name is OK,os it is stored in the session.and 
      #the user is moved into the main room 
      session.name=name 
      session.enter(self.server.main_room) 

class ChatRoom(Room): 
    ''' 
    A room meant for multiple users who can chat with the others in the room 
    ''' 

    def add(self,session): 
     #Notify everyone that a new user has entered 
     self.broadcast('{0} has entered the room.\r\n'.format(session.name)) 
     self.server.users[session.name]=session 
     Room.add(self,session) 

    def remove(self,session): 
     Room.remove(self,session) 
     #Notify everyone that a user has left 
     self.broadcast('{0} has left the room.\r\n'.format(session.name)) 

    def do_say(self,session,line): 
     self.broadcast('{0}: '+line+'\r\n'.format(session.name)) 

    def do_look(self,session,line): 
     'Handles the look command,used to see who is in a room' 
     session.push('The following are in this room:\r\n'.encode()) 
     for other in self.sessions: 
      session.push('{0}\r\n'.format(other.name).encode()) 

    def do_who(self,session,line): 
     'Handles the who command ,used to see who is logged in' 
     session.push('The following are logged in:\r\n'.encode()) 
     for name in self.server.users: 
      session.push('{0}\r\n'.format(name)) 

class LogoutRoom(Room): 
    ''' 
    A simple room for a single user.Its sole purpose is to remove the user's name from the server 
    ''' 

    def add(self,session): 
     #When a session (user) enters the LogoutRoom it is deleted 

     try: 
      del self.server.users[session.name] 
     except KeyError: 
      pass 

class ChatSession(async_chat): 
    ''' 
    A single session,which takes care of the communication with a single user 
    ''' 

    def __init__(self,server,sock): 
     # async_chat.__init__(self,sock) 
     super().__init__(sock) 
     self.server=server 
     self.set_terminator('\r\n') 
     self.data=[] 
     self.name=None 
     #All sessions begin in a separate LoginRoom 
     self.enter(LoginRoom(server)) 

    def enter(self,room): 
     # Remove self from current room and add self to next room.... 
     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): 
    ''' 
    A chat server with a single room 
    ''' 

    def __init__(self,port,name): 
     super().__init__() 
     # 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() 

Ne bana bu hatayı veriyor sorun nedir?

traceback

error: uncaptured python exception, closing channel <__main__.ChatSession connected 
127.0.0.1:39939 at 0x7f14b1f07d68> 
(<class 'TypeError'>:Type str doesn't support the buffer API 
[/usr/lib/python3.4/asyncore.py|read|83] [/usr/lib/python3.4/asyncore.py|handle_read_event|442] 
[/usr/lib/python3.4/asynchat.py|handle_read|154]) 
+0

söylemek unutmak, python3 sürümü 3.4.0 – tcstory

+0

olduğunu Okunabilirliği sağlamak için bu geri izlemeyi sorgunuza kopyalayıp yapıştırabilirsiniz. – Evert

+0

Bir tahminde: “bytes” nesnesini kullanmanız gereken bir Python 3 (unicode) dizesi kullanıyorsunuz. – Evert

cevap

21

iki kodunuzda sorun vardır: set_terminator() çağrılması

  1. str

    use_encoding ayarlanmadığı sürece sen bu yöntemi bytes nesneyi besleyelim asynchat.py Okuma ile True (önerilmez). Senin durumunda yapmanız gereken:

     self.set_terminator(b'\r\n') 
    
  2. datastr Python 3

    collect_incoming_data() yılında, veri nesneleri bytes olan soket alınan bir varsayarsak. neye ihtiyacınız str Yani eğer, önce deşifre etmelidir:

    def collect_incoming_data(self, data): 
         self.data.append(data.decode('utf-8')) 
    

Ayrıca bkz kaynak kodu: http://hg.python.org/cpython/file/c0e311e010fc/Lib/asynchat.py

+0

Bağlantınızı kaynak koduna okuma 118 numaralı satırda "bytes (str, self.encoding)' yi okuyorum. Bunun yerine bayt (data, self.encoding) 'olmalıdır? Henüz tüm mantıktan geçmedim. – Ryan

+0

@Ryan iyi yakalama! Ben Python stdlib – fantix

+0

@Ryan bir hata olduğunu düşünüyorum, bu bir hata değil, çünkü kod değiştirmeme yardımcı olan bir kişi sorunu vardı, o, hatta bayt (str, self.encoding) bayt değiştirdi, test etmişti veri, self.encoding), sorun hala burada. Bu bir hata olduğunu düşünmüyorum – tcstory

1
from asyncore import dispatcher 
from asynchat import async_chat 
import socket, asyncore 

PORT = 5005 
NAME = 'TestChat' 

class EndSession(Exception): pass 

class CommandHandler: 
    """ 
    Simple command handler similar to cmd.Cmd from the standard library. 
    """ 

    def unknown(self, session, cmd): 
     'Respond to an unknown command' 
     session.push('Unknown command: {}s\r\n'.format(cmd).encode('utf-8')) 

    def handle(self, session, line): 
     'Handle a received line from a given session' 
     if not line.strip(): return 
     # Split off the command: 
     parts = line.split(' ', 1) 
     cmd = parts[0] 
     try: line = parts[1].strip() 
     except IndexError: line = '' 
     # Try to find a handler: 
     meth = getattr(self, 'do_' + cmd, None) 
     try: 
      # Assume it's callable: 
      meth(session, line) 
     except TypeError: 
      # If it isn't, respond to the unknown command: 
      self.unknown(session, cmd) 

class Room(CommandHandler): 
    """ 
    A generic environment that may contain one or more users (sessions). 
    It takes care of basic command handling and broadcasting. 
    """ 

    def __init__(self, server): 
     self.server = server 
     self.sessions = [] 

    def add(self, session): 
     'A session (user) has entered the room' 
     self.sessions.append(session) 

    def remove(self, session): 
     'A session (user) has left the room' 
     self.sessions.remove(session) 

    def broadcast(self, line): 
     'Send a line to all sessions in the room' 
     for session in self.sessions: 
      session.push(line) 

    def do_logout(self, session, line): 
     'Respond to the logout command' 
     raise EndSession 

class LoginRoom(Room): 
    """ 
    A room meant for a single person who has just connected. 
    """ 

    def add(self, session): 
     Room.add(self, session) 
     # When a user enters, greet him/her: 
     self.broadcast('Welcome to {}\r\n'.format(self.server.name).encode('utf-8')) 

    def unknown(self, session, cmd): 
     # All unknown commands (anything except login or logout) 
     # results in a prodding: 
     session.push('Please log in\nUse "login <nick>"\r\n'.encode('utf-8')) 

    def do_login(self, session, line): 
     name = line.strip() 
     # Make sure the user has entered a name: 
     if not name: 
      session.push('Please enter a name\r\n'.encode('utf-8')) 
     # Make sure that the name isn't in use: 
     elif name in self.server.users: 
      session.push('The name "{}" is taken.\r\n'.format(name).encode('utf-8')) 
      session.push('Please try again.\r\n'.encode('utf-8')) 
     else: 
      # The name is OK, so it is stored in the session, and 
      # the user is moved into the main room. 
      session.name = name 
      session.enter(self.server.main_room) 

class ChatRoom(Room): 
    """ 
    A room meant for multiple users who can chat with the others in the room. 
    """ 

    def add(self, session): 
     # Notify everyone that a new user has entered: 
     self.broadcast((session.name + ' has entered the room.\r`enter code here`\n').encode('utf-8')) 
     self.server.users[session.name] = session 
     super().add(session) 

    def remove(self, session): 
     Room.remove(self, session) 
     # Notify everyone that a user has left: 
     self.broadcast((session.name + ' has left the room.\r\n').encode('utf-8')) 

    def do_say(self, session, line): 
     self.broadcast((session.name + ': ' + line + '\r\n').encode('utf-8')) 

    def do_look(self, session, line): 
     'Handles the look command, used to see who is in a room' 
     session.push('The following are in this room:\r\n'.encode('utf-8')) 
     for other in self.sessions: 
      session.push((other.name + '\r\n').encode('utf-8')) 

    def do_who(self, session, line): 
     'Handles the who command, used to see who is logged in' 
     session.push('The following are logged in:\r\n'.encode('utf-8')) 
     for name in self.server.users: 
      session.push((name + '\r\n').encode('utf-8')) 

class LogoutRoom(Room): 
    """ 
    A simple room for a single user. Its sole purpose is to remove the 
    user's name from the server. 
    """ 

    def add(self, session): 
     # When a session (user) enters the LogoutRoom it is deleted 
     try: del self.server.users[session.name] 
     except KeyError: pass 

class ChatSession(async_chat): 
    """ 
    A single session, which takes care of the communication with a single user. 
    """ 

    def __init__(self, server, sock): 
     super().__init__(sock) 
     self.server = server 
     self.set_terminator(b"\r\n") 
     self.data = [] 
     self.name = None 
     # All sessions begin in a separate LoginRoom: 
     self.enter(LoginRoom(server)) 

    def enter(self, room): 
     # Remove self from current room and add self to 
     # next room... 
     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.decode('utf-8')) 

    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): 
    """ 
    A chat server with a single room. 
    """ 

    def __init__(self, port, name): 
     super().__init__() 
     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() 
+0

python 3.61 iyi çalışıyor – yuying

İlgili konular