import threading
import select


class Client(object):
    def __init__(self, sock, address, host):
        self.socket = sock
        self.server = host
        self.address = address
        self.connected = True
        self.exit_request = False

        self.thread = ClientThread(self)
        self.thread.start()

        self.socket.setblocking(0)

    def disconnect(self):
        self.exit_request = True


class ClientThread(threading.Thread):
    def __init__(self, parent):
        super(ClientThread, self).__init__()
        self.parent = parent

    def run(self):
        while not self.parent.exit_request:
            ready_to_read, ready_to_write, in_error = select.select(
                [self.parent.socket], [], [], 2
            )
            if self.parent.socket not in ready_to_read:
                continue
            data = self.parent.socket.recv(1024)
            if not data:
                break
            self.parent.socket.sendall(data)

        self.parent.socket.sendall('Bye!')
        self.parent.socket.close()
        self.parent.connected = False

import threading
import select


class Client(object):
    def __init__(self, sock, address, host):
        self.socket = sock
        self.server = host
        self.address = address
        self.connected = True
        self.exit_request = False

        self.thread = ClientThread(self)
        self.thread.start()

        self.socket.setblocking(0)

    def on_receive(self, data):
        pass

    def send(self, data):
        self.socket.sendall(data)

    def disconnect(self):
        self.exit_request = True


class ClientThread(threading.Thread):
    def __init__(self, parent):
        super(ClientThread, self).__init__()
        self.parent = parent

    def run(self):
        while not self.parent.exit_request:
            ready_to_read, ready_to_write, in_error = select.select(
                [self.parent.socket], [], [], 2
            )
            if self.parent.socket not in ready_to_read:
                continue
            data = self.parent.socket.recv(1024)
            if not data:
                break
            self.parent.on_receive(data)

        self.parent.socket.sendall('Bye!')
        self.parent.socket.close()
        self.parent.connected = False

Add on_receive and send methods.
Add on_receive and send methods.

on_receive method is called when a new data is got.
send method is used to send data to the client.

  import threading
  import select
  
  
  class Client(object):
      def __init__(self, sock, address, host):
          self.socket = sock
          self.server = host
          self.address = address
          self.connected = True
          self.exit_request = False
  
          self.thread = ClientThread(self)
          self.thread.start()
  
          self.socket.setblocking(0)
+ 
+     def on_receive(self, data):
+         pass
+ 
+     def send(self, data):
+         self.socket.sendall(data)
  
      def disconnect(self):
          self.exit_request = True
  
  
  class ClientThread(threading.Thread):
      def __init__(self, parent):
          super(ClientThread, self).__init__()
          self.parent = parent
  
      def run(self):
          while not self.parent.exit_request:
              ready_to_read, ready_to_write, in_error = select.select(
                  [self.parent.socket], [], [], 2
              )
              if self.parent.socket not in ready_to_read:
                  continue
              data = self.parent.socket.recv(1024)
              if not data:
                  break
-             self.parent.socket.sendall(data)
+             self.parent.on_receive(data)
  
          self.parent.socket.sendall('Bye!')
          self.parent.socket.close()
          self.parent.connected = False
  
Add on_receive and send methods.
## Code Before:
import threading
import select


class Client(object):
    def __init__(self, sock, address, host):
        self.socket = sock
        self.server = host
        self.address = address
        self.connected = True
        self.exit_request = False

        self.thread = ClientThread(self)
        self.thread.start()

        self.socket.setblocking(0)

    def disconnect(self):
        self.exit_request = True


class ClientThread(threading.Thread):
    def __init__(self, parent):
        super(ClientThread, self).__init__()
        self.parent = parent

    def run(self):
        while not self.parent.exit_request:
            ready_to_read, ready_to_write, in_error = select.select(
                [self.parent.socket], [], [], 2
            )
            if self.parent.socket not in ready_to_read:
                continue
            data = self.parent.socket.recv(1024)
            if not data:
                break
            self.parent.socket.sendall(data)

        self.parent.socket.sendall('Bye!')
        self.parent.socket.close()
        self.parent.connected = False

## Instruction:
Add on_receive and send methods.
## Code After:
import threading
import select


class Client(object):
    def __init__(self, sock, address, host):
        self.socket = sock
        self.server = host
        self.address = address
        self.connected = True
        self.exit_request = False

        self.thread = ClientThread(self)
        self.thread.start()

        self.socket.setblocking(0)

    def on_receive(self, data):
        pass

    def send(self, data):
        self.socket.sendall(data)

    def disconnect(self):
        self.exit_request = True


class ClientThread(threading.Thread):
    def __init__(self, parent):
        super(ClientThread, self).__init__()
        self.parent = parent

    def run(self):
        while not self.parent.exit_request:
            ready_to_read, ready_to_write, in_error = select.select(
                [self.parent.socket], [], [], 2
            )
            if self.parent.socket not in ready_to_read:
                continue
            data = self.parent.socket.recv(1024)
            if not data:
                break
            self.parent.on_receive(data)

        self.parent.socket.sendall('Bye!')
        self.parent.socket.close()
        self.parent.connected = False
