2014-07-24 11 views
17

मैं python3 करने को Python2 कन्वर्ट करने के लिए कोशिश कर रहा हूँ का समर्थन नहीं करता, मैं एक त्रुटि है: प्रोग्राम को कनेक्ट करने के लिए इस आदेश "टेलनेट स्थानीय होस्ट 5005" का उपयोग, लेकिन प्रवेश करने के लिए जब मैं कोशिश, एक समस्या सुचित किया गया था।python3 प्रकार str बफर एपीआई

स्क्रीनशॉट:

कोड:

#!/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() 

क्या समस्या है कि मुझे इस त्रुटि दे रही है?

ट्रैस बैक

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

कहने के लिए भूल जाते हैं, python3 के संस्करण 3.4.0 – tcstory

+0

है क्या आप पठनीयता के लिए अपने प्रश्न में उस ट्रेसबैक को कॉपी-पेस्ट कर सकते हैं। – Evert

+0

एक अनुमान पर: यदि आप एक अजगर 3 (यूनिकोड) स्ट्रिंग है जहाँ आप एक 'bytes' वस्तु का उपयोग कर किया जाना चाहिए का उपयोग कर रहे हैं। – Evert

उत्तर

21

वहाँ अपने कोड में दो मुद्दे हैं: str

पढ़ना asynchat.py आप इस विधि का एक bytes वस्तु खिलाने चाहिए, जब तक use_encoding पर सेट है साथ

  1. set_terminator() कॉलिंग True (जो अनुशंसित नहीं है)। आपके मामले में आपको क्या करना चाहिए:

     self.set_terminator(b'\r\n') 
    
  2. मान लिया जाये कि datastrcollect_incoming_data()

    में अजगर 3 में, डेटा सॉकेट से प्राप्त वस्तुओं bytes हो रहा है। तो अगर आप क्या जरूरत है एक str है, तो आपको पहले डिकोड करना चाहिए:

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

भी देखें स्रोत कोड: http://hg.python.org/cpython/file/c0e311e010fc/Lib/asynchat.py

+0

स्रोत कोड मैं लाइन 118 पढ़ने 'बाइट (str, self.encoding)' पर देखने के लिए आपके लिंक पढ़ना। क्या यह 'बाइट्स (डेटा, self.encoding)' होना चाहिए? अभी तक पूरे तर्क से गुजर चुके नहीं हैं। – Ryan

+0

@ रयान अच्छा पकड़ो! मुझे विश्वास है कि अजगर में एक बग – fantix

+0

stdlib @Ryan मैं लगता है कि एक बग नहीं है, क्योंकि एक है जो मेरी मदद कोड को संशोधित मुद्दा मिल गया था, वह परीक्षण किया था, यहां तक ​​कि बाइट्स बाइट (str, self.encoding) (बदल रहा है डेटा, self.encoding), समस्या अभी भी here.so मैं लगता है कि एक बग – 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

अजगर 3.61 काम अच्छी तरह से – yuying

संबंधित मुद्दे