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)\Python\lib\multiprocessing\process.py", line 314, in _bootstrap
self.run()
File "F:\Program Files (x86)\Python\lib\multiprocessing\process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "f:\project\mainmenu.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?
CodePudding user response:
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