0

I have a simple chat application with server and client code in Python. In the server side the class Client defines the following

class Client(object):
    def __init__(self, socket, address):
     self.sock = socket
     self.addr = address
     self.room = None
     self.name = None
     self._is_online = True
     thread = threading.Thread(target=self.run, args=())
     thread.daemon = True
     thread.start()

As you can see the server handles every client as a different thread. On the main thread the server runs in a always-true loop

while True:
(ready_to_read, _, _) = select.select([server_sckt] + [Client.sock for Client in clients], [], [])
for connection in ready_to_read:
    if connection == server_sckt:
        (connection, address) = server_sckt.accept()
        clients.append( Client(connection, address) )

clients is the list containing all Client objects. The problem comes in the second loop iteration.

Traceback (most recent call last):
 File "servidor_class.py", line 215, in <module>
  clients.append( Client(connection, address) )
TypeError: 'Client' object is not callable

So it's clear I'm not getting pythonic OOP way to declare each instance.

I've looked another related questions:

  1. Creating object instances in a loop with independent handling
  2. Python creating multiple instances for a single object/class

But I'm still not seeing my mistake instancing, sure it's in front of me. Without appending to a list seems to work but main server functionalities like send message to all online people or check if username if already used doesn't work.

2
  • Perhaps it is simply a copy&paste error. But, have you tried indenting the __init__ method by four spaces? Indentation in Python is mandatory, and for a function to belong to a class, it must be indented by four spaces under the class header. Commented May 17, 2017 at 17:20
  • Oh yes, copy paste error, is indented @ChristianDean :) Edited Commented May 17, 2017 at 17:27

1 Answer 1

3

In Python 2, list comprehensions leak the control variable: See this question

The problem is a few lines above where the exception actually happens in the select line

#                                                                      | Here
#                                                                      v
(ready_to_read, _, _) = select.select([server_sckt] + [Client.sock for Client in clients], [], [])

In the list comprehension you redefine what Client means. It becomes an instance of the Client class. So when you try to create another instance using an existing instance instead of a class, it raises an exception.

Change the list comprehension part to

#                | notice the lower case.
#                v
[client.sock for client in clients]

Or anything else besides Client

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.