Python:如何从类外部调用方法?

时间:2013-08-08 15:13:26

标签: python class

我有一个非常简短的问题:

如何从另一个python文件/类调用send()方法? 我想从另一个组件向客户端发送消息(建立连接)。

我认为我必须得到单例实例的引用,然后像这样“发送”:

server = Server(ip,port)
server.send("hello")

如果我这样做,我会收到错误:

NoneType' object has no attribute 'send'

也许“自我”就是问题......

这是服务器类:

class Server(threading.Thread):

    ##############################################################################
    # Server: Singleton Instance
    ##############################################################################
    _instance = None
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Server, cls).__new__(cls, *args, **kwargs)
        return cls._instance    

    ##############################################################################
    # Constructor of Server
    ##############################################################################
    def __init__(self, host, port):
        threading.Thread.__init__(self)
        print "[SERVER____] Creating Server Thread"
        self.host = host
        self.port = port
        self.__reset__()  

    ##############################################################################
    # Resetting local attributes
    ##############################################################################
    def __reset__(self):   
        print "[SERVER____] Reset"         
        self.serverSock = None
        self.clientSock = None
        self.clientAddr = None
        self.clientData = None
        self.isRunning = None
        self.isWaiting = None

    ###########################################################################                
    def send(self, message):
        print "[SERVER____] Sending Message", message
        self.clientSock.send(message)

    ##############################################################################
    # Stop the Server: Close the Socket and Reset
    ##############################################################################
    def stop(self):            
        # Close The Client Socket
        if(self.clientSock): 
            self.clientSock.close()
            print "[SERVER____] Aborting Client Socket"
        # Close The Server Socket    
        if(self.serverSock): 
            self.serverSock.close()
            print "[SERVER____] Aborting Server Socket"
        # Reset the Member Fields
        self.__reset__()
        print "[SERVER____] Aborting Server Thread"
        self._Thread__stop()

    ##############################################################################
    # Server.start()
    ##############################################################################
    def run(self):          
        try:
            # Create The Socket
            self.serverSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            print "[SERVER____] Creating Server Socket"
            # Set Socket Options
            #self.serverSock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1);
            # Bind The New Socket
            self.serverSock.bind((self.host, self.port))
            print "[SERVER____] Binding Server Socket"
            print "[SERVER____] IP: ", self.host, " Port: ", self.port
            # Set The Awaiting Flag
            self.isWaiting = True;
            # Start The Server Loop
            while self.isWaiting:
                # Listen On New Socket
                self.serverSock.listen(1)
                print "[SERVER____] Listening Server Socket"
                # Accept New Connection            
                self.clientSock, self.clientAddr = self.serverSock.accept()     
                print "[SERVER____] Accepting New Connection: " , self.clientAddr
                # Set The Running Flag
                self.isRunning = True;     
                # Serve The Connection
                while self.isRunning:
                    print "[SERVER____] Want to recv message...."
                    try:
                        # Receive A New Data Block    
                        self.clientData = self.clientSock.recv(config.BUFFERSIZE)
                        # Process The New Data Block
                        if not self.clientData:                       
                            print "[SERVER____] Reset By Client Connection"
                            break
                        else:    
                            print "[SERVER____] Receiving Message: ", self.clientData
                            parser = MessageParser()
                            parser.parseSMMessage(self.clientData)                    
                    except socket.error:
                        print "[SERVER_ERR] Error at receiving data from client."                            
        except Exception as exc:
            print "[SERVER____] Server Thread Exception ", exc

1 个答案:

答案 0 :(得分:1)

您对单例模式的实现是错误的,这会导致self.clientSock在调用None之前设置为self.clientSock.send。实现是错误的,因为每次获得单例实例时它都会调用__init__。基本上,会发生什么:

  1. 您致电Server(...)以获取实例。
  2. 在该实例上调用
  3. run。这会设置self.clientSock
  4. 您致电Server(...)再次获取该实例。由于您__new__的实施,这将返回相同的实例,但会再次调用__init__self.clientSock将重置为None
  5. 现在,对self.clientSock.send的调用会导致异常。
  6. 如果你需要,我建议避免使用__new__来实现单例(虽然根本不使用单例可能是最好的)。列出了其他一些方法here