For loop does not continue after exception occurs on Python

Question:

This piece of code runs on different threads for connected clients. When a client disconnects, the try-except block should raise an exception, and remove the client from the clients list (connectClients is also a list, I used this to prevent the error that occurs when the size of the iterable changes during the iteration). After that, it should continue the loop and send the message to the next client (if they are still connected), but that doesn’t happen, the loop just stops. After displaying "A client has disconnected" and sending the message to all the clients on the list before the client that raised the exception, it works properly again.

    def communicateServer(self, msg):
        # Add try except to remove connections
        self.connectedClients = self.clients
        i = 0
        for client in self.clients:
            try:
                client.send(msg)
                print("Sending message...")
                i += 1
            except:
                print("A client has disconnected")
                self.connectedClients.pop(i)
                i += 1
                continue
        self.clients = self.connectedClients

I’ve already tried continue and pass, expecting the loop to go to the next iteration, but it didn’t work. The loop still stopped. Note that I’m not removing items from the list I’m iterating on (clients). And yes, I know I could use enumerate() on this code, but since the elements of the list are socket connections, Python understands it as keyword arguments and doesn’t allow the use of enumerate.

Asked By: enid

||

Answers:

I’m not removing items from the list I’m iterating on (clients)

But you actually removing them, with self.connectedClients = self.clients you are creating a reference to the self.clients (so you are modifying the same object) so you need a new list:

self.connectedClients = self.clients.copy()

Also I can’t see the issue if you will use enumerate (that’s probably more efficient than copying large enough lists) like this:

for index, client in enumerate(self.clients):

If you have an error using enumerate please provide more details on it

Answered By: svfat