How to append client names to listbox?

Question:

I have a listbox that, when server accepts a connection, should display the names of the clients. The server code is as follows:

class GUI2(GUI): #server GUI

    def __init__(self):

        self.clientlist = tk.Listbox(self.clientframe) #listbox  that should display client names
        self.clientlist.pack(expand = 1)

        self.s = INITSERVER()
    
        self.process = Process(target = self.s.startChat) #prevents the GUI from freezing due to server running

        self.process.start()

class INITSERVER(GUI2): 

      def startChat(self): #starts the server
   
          print("server is working on " + self.SERVER)
    
          self.server.listen(30) #sets max number to only 30 clients

          while True:
            
                self.conn, self.addr = self.server.accept()
            
                self.name = self.conn.recv(1024).decode(self.FORMAT)

                self.clientlist.insert("end", self.name) #append client names to listbox supposedly

                print(f"Name is :{self.name}")

The client code is as follows:

class INITCLIENT(GUI3): #GUI3 is client GUI; calls INITCLIENT when done packing

    def __init__(self):

        self.PORT = 5000
        self.SERVER = "" #left blank for this post; contains the server's exact address
        self.ADDRESS = (self.SERVER, self.PORT)
        self.FORMAT = "utf-8"

        self.client = socket.socket(socket.AF_INET,
                   socket.SOCK_STREAM)

        self.client.connect(self.ADDRESS)

        self.name = g.entergname.get() # g = GUI() i.e. root window; entergname is Entry widget where client inputs their names

        self.client.send(self.name.encode(self.FORMAT)) #sends inputted names to INITSERVER to display in listbox.... supposedly

Through VS Code, I run the server first, then join the server using another terminal; the problem happens next.

Process Process-1:
Traceback (most recent call last):
  File "F:Program Files (x86)Pythonlibmultiprocessingprocess.py", line 314, in _bootstrap
    self.run()
  File "F:Program Files (x86)Pythonlibmultiprocessingprocess.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "f:projectmainmenu.py", line 341, in startChat
    self.clientlist.insert("end", self.name) #append client names to listbox
AttributeError: 'INITSERVER' object has no attribute 'clientlist'`

I tried replacing self.clientlist.insert to super().clientlist.insert but the same error pops up with `AttributeError: ‘super’ object has no attribute ‘clientlist’

Any help in fixing the error, or in pointing me to the right direction is greatly appreciated.

EDIT: So after countless trial and error, I think the error is caused by the duplicate/child processes not knowing what is self.clientlist because they don’t know that self (i.e. INITSERVER) is a child of GUI2; Process doesn’t duplicate the parent attributes, only the ones within the function of Startchat().

Is there a way to restructure the code so that the clients’ names can be displayed through listbox? Or is what I’m doing not compatible with Python and I have to display it in some other way?

Asked By: N. Tanaka

||

Answers:

Thanks to @acw1668 I was guided to the answer: I just needed to remove the INITSERVER class and move all of its functions and attributes to GUI2 class, then use Threading instead of Process to target startChat to bypass Tkinter pickle errors. The new code is as follows:

class GUI2(GUI): #server GUI

    def __init__(self):

        self.clientlist = tk.Listbox(self.clientframe) #listbox  that should display client names
        self.clientlist.pack(expand = 1)


        self.thread = Thread(target = self.startChat) #prevents the GUI from freezing due to server running

        self.thread.start()

    def startChat(self):

        if (self.checksignal == 0): #custom-made stop signal for stopping the thread
   
            print("server is working on " + self.SERVER)
    
            self.server.listen(30)

            while True:
            
                self.conn, self.addr = self.server.accept()
           
                self.name = self.conn.recv(1024).decode(self.FORMAT)

                self.clientlist.insert("end", self.name) #append client names to listbox


        else:

            return  
Answered By: N. Tanaka
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.