title: Send and receive objects through sockets in Python
body: <p>I have searched a lot on the Internet, but I haven't been able to find the solution to send an object over the socket and receive it as is. I know it needs pickling which I have already done. And that converts it to bytes and is received on the other hand. But how can I convert those bytes to that type of object?</p>
  <pre><code>process_time_data = (current_process_start_time, current_process_end_time)
  prepared_process_data = self.prepare_data_to_send(process_time_data)
  data_string = io.StringIO(prepared_process_data)
  data_string =  pack('&gt;I', len(data_string)) + data_string
  self.send_to_server(data_string)
  </code></pre>
  <p>This is the code which is converting the object to StringIO on the client and sending to the server. And on the server side I am getting bytes. Now I am searching for bytes to be converted to StringIO again so that I can get the object value.</p>
  <p>In the code, Object is wrapped in StringIO and is being sent over the socket. Is there a better approach?</p>
  <p>The server-side code is as follows.</p>
  <pre><code>server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  #server.setblocking(0)
  server.bind(('127.0.0.1', 50000))
  server.listen(5)
  inputs = [server]
  outputs = []
  message_queues = {}
  
  while inputs:
      readable, writeable, exceptional = select.select(inputs, outputs, inputs)
      for s in readable:
          if s is server:
              connection, client_address = s.accept()
              print(client_address)
              connection.setblocking(0)
              inputs.append(connection)
              message_queues[connection] = queue.Queue()
              print('server started...')
          else:
              print('Getting data step 1')
              raw_msglen = s.recv(4)
              msglen = unpack('&gt;I', raw_msglen)[0]
              final_data = b''
              while len(final_data) &lt; msglen:
                  data = s.recv(msglen - len(final_data))
                  if data:
                      #print(data)
                      final_data += data
                      message_queues[s].put(data)
                      if s not in outputs:
                          outputs.append(s)
                      else:
                          if s in outputs:
                              outputs.remove(s)
                  else:
                      break
              inputs.remove(connection)
              #s.close()
              del message_queues[s]
  
              process_data = ProcessData()
              process_screen = ProcessScreen()
  
              if final_data is not None:
                  try:
                      deserialized_data = final_data.decode(&quot;utf-8&quot;)
                      print(deserialized_data)
                  except (EOFError):
                      break
              else:
                  print('final data is empty.')
  
              print(process_data.project_id)
              print(process_data.start_time)
              print(process_data.end_time)
              print(process_data.process_id)
  </code></pre>
  <p>The two helper functions are as follows:</p>
  <pre><code>def receive_all(server, message_length, message_queues, inputs, outputs):
      # Helper function to recv message_length bytes or return None if EOF is hit
      data = b''
      while len(data) &lt; message_length:
          packet = server.recv(message_length - len(data))
          if not packet:
              return None
          data += packet
          message_queues[server].put(data)
          if server not in outputs:
              outputs.append(server)
          else:
              if server in outputs:
                  outputs.remove(server)
      inputs.remove(server)
      del message_queues[server]
      return data
  
  
  def receive_message(server, message_queues, inputs, outputs):
      # Read message length and unpack it into an integer
      raw_msglen = receive_all(server, 4, message_queues, inputs, outputs)
      if not raw_msglen:
          return None
      message_length = unpack('&gt;I', raw_msglen)[0]
  
      return receive_all(server, message_length, message_queues, inputs, outputs)
  </code></pre>
  <p>And two of the model classes are as follows:</p>
  <pre><code>class ProcessData:
      process_id = 0
      project_id = 0
      task_id = 0
      start_time = 0
      end_time = 0
      user_id = 0
      weekend_id = 0
  
  # Model class to send image data to the server
  class ProcessScreen:
      process_id = 0
      image_data = bytearray()
  </code></pre>