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: Read local python code and store them in a dictionary, which will
  then be sent to the job.
  
  Args:
      distributed_files (list): A list of files to be distributed at all
                                remote instances(e,g. the configuration
                                file for initialization) . RegExp of file
                                names is supported. 
                                e.g. 
                                    distributed_files = ['./*.npy', './test*']
                                                                       
  Returns:
      A cloudpickled dictionary containing the python code in current
      working directory.
docstr_tok: ["Read","local","python","code","and","store","them","in","a","dictionary",",","which","will","then","be","sent","to","the","job",".","Args",":","distributed_files","(","list",")",":","A","list","of","files","to","be","distributed","at","all","remote","instances","(","e",",","g",".","the","configuration","file","for","initialization",")",".","RegExp","of","file","names","is","supported",".","e.g",".","distributed_files","=","[","'.\/","*",".npy","'",",","'.\/test","*","'","]","Returns",":","A","cloudpickled","dictionary","containing","the","python","code","in","current","working","directory","."]
code: def read_local_files(self, distributed_files=[]):
      """Read local python code and store them in a dictionary, which will
      then be sent to the job.
  
      Args:
          distributed_files (list): A list of files to be distributed at all
                                    remote instances(e,g. the configuration
                                    file for initialization) . RegExp of file
                                    names is supported.
                                    e.g.
                                        distributed_files = ['./*.npy', './test*']
  
      Returns:
          A cloudpickled dictionary containing the python code in current
          working directory.
      """
      pyfiles = dict()
      pyfiles["python_files"] = {}
      pyfiles["other_files"] = {}
  
      user_files = []
      user_empty_subfolders = []
  
      for distributed_file in distributed_files:
          parsed_list = glob.glob(distributed_file)
          if not parsed_list:
              raise ValueError(
                  "no local file is matched with '{}', please check your input".format(
                      distributed_file
                  )
              )
          for pathname in parsed_list:
              if os.path.isdir(pathname):
                  (
                      pythonfiles,
                      otherfiles,
                      emptysubfolders,
                  ) = get_subfiles_recursively(pathname)
                  user_files.extend(pythonfiles)
                  user_files.extend(otherfiles)
                  user_empty_subfolders.extend(emptysubfolders)
              else:
                  user_files.append(pathname)
  
      if isnotebook():
          main_folder = "./"
      else:
          main_file = sys.argv[0]
          main_folder = "./"
          sep = os.sep
          if sep in main_file:
              main_folder = sep.join(main_file.split(sep)[:-1])
      code_files = filter(
          lambda x: x.endswith(".py"), os.listdir(main_folder)
      )
  
      for file_name in code_files:
          file_path = os.path.join(main_folder, file_name)
          assert os.path.exists(file_path)
          with open(file_path, "rb") as code_file:
              code = code_file.read()
              pyfiles["python_files"][file_name] = code
  
      for file_name in set(user_files):
          assert os.path.exists(file_name)
          assert not os.path.isabs(
              file_name
          ), "[XPARL] Please do not distribute a file with absolute path."
          with open(file_name, "rb") as f:
              content = f.read()
              pyfiles["other_files"][file_name] = content
  
      pyfiles["empty_subfolders"] = set(user_empty_subfolders)
      return cloudpickle.dumps(pyfiles)
  
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 4 for calling the Client obj's underlying member method code with example usage: obj.read_local_files(distributed_files) and returns: cloudpickle