class_docstr: Base class for the remote client.
  
  For each training task, there is a global client in the cluster which
  submits jobs to the master node. Different `@parl.remote_class` objects
  connect to the same global client in a training task.
  
  Attributes:
      submit_job_socket (zmq.Context.socket): A socket which submits job to
                                              the master node.
      pyfiles (bytes): A serialized dictionary containing the code of python
                       files in local working directory.
      executable_path (str): File path of the executable python script.
      start_time (time): A timestamp to record the start time of the program.
class_docstr_tok: ["Base","class","for","the","remote","client",".","For","each","training","task",",","there","is","a","global","client","in","the","cluster","which","submits","jobs","to","the","master","node",".","Different","`","@","parl.remote_class","`","objects","connect","to","the","same","global","client","in","a","training","task",".","Attributes",":","submit_job_socket","(","zmq.Context.socket",")",":","A","socket","which","submits","job","to","the","master","node",".","pyfiles","(","bytes",")",":","A","serialized","dictionary","containing","the","code","of","python","files","in","local","working","directory",".","executable_path","(","str",")",":","File","path","of","the","executable","python","script",".","start_time","(","time",")",":","A","timestamp","to","record","the","start","time","of","the","program","."]
docstr: Args:
      master_addr (str): IP address of the master node.
      job_heartbeat_server_addr(str): Server address for heartbeat detection from jobs.
      process_id (str): Process id in which client is created. Should use os.getpid() to get the process id.
      distributed_files (list): A list of files to be distributed at all remote instances(e,g. the configuration
                                file for initialization) .
docstr_tok: ["Args",":","master_addr","(","str",")",":","IP","address","of","the","master","node",".","job_heartbeat_server_addr","(","str",")",":","Server","address","for","heartbeat","detection","from","jobs",".","process_id","(","str",")",":","Process","id","in","which","client","is","created",".","Should","use","os.getpid","(",")","to","get","the","process","id",".","distributed_files","(","list",")",":","A","list","of","files","to","be","distributed","at","all","remote","instances","(","e",",","g",".","the","configuration","file","for","initialization",")","."]
code: def __init__(self, master_address, process_id, distributed_files=[]):
      """
      Args:
          master_addr (str): IP address of the master node.
          job_heartbeat_server_addr(str): Server address for heartbeat detection from jobs.
          process_id (str): Process id in which client is created. Should use os.getpid() to get the process id.
          distributed_files (list): A list of files to be distributed at all remote instances(e,g. the configuration
                                    file for initialization) .
      """
      self.dead_job_queue = mp.Queue()
      self.client_is_alive = mp.Value("i", True)
      self._create_heartbeat_server()
      th = threading.Thread(
          target=self._update_job_status, args=(self.dead_job_queue,)
      )
      th.setDaemon(True)
      th.start()
      self.master_address = master_address
      self.process_id = process_id
      self.ctx = zmq.Context()
      self.lock = threading.Lock()
      self.log_monitor_url = None
      self.threads = []
      self.executable_path = self.get_executable_path()
      self._create_sockets(master_address)
      self.connected_to_master = True
      self.check_env_consistency()
      self.instance_count = 0
      self.instance_id_to_job = dict()
  
      thread = threading.Thread(
          target=self._update_client_status_to_master
      )
      thread.setDaemon(True)
      thread.start()
      self.threads.append(thread)
  
      self.pyfiles = self.read_local_files(distributed_files)
  
imports: import cloudpickle
  import datetime
  import os
  import socket
  import sys
  import threading
  import zmq
  import parl
  import time
  import glob
  import multiprocessing
  from parl.utils import to_str, to_byte, get_ip_address, logger, isnotebook
  from parl.remote.utils import get_subfiles_recursively
  from parl.remote import remote_constants
  from parl.remote.grpc_heartbeat import HeartbeatServerThread, HeartbeatServerProcess
  from parl.remote.utils import get_version
label_desc: Use image node_id 1 to create a new Client object from inherited base classes: object with example: obj = Client(master_address, process_id, distributed_files)