code: def main_loop(args):
      """main loop logic for trial keeper"""
      global _trial_process
  
      if not os.path.exists(LOG_DIR):
          os.makedirs(LOG_DIR)
  
      trial_keeper_syslogger = RemoteLogger(
          args.nnimanager_ip,
          args.nnimanager_port,
          "trial_keeper",
          StdOutputType.Stdout,
          args.log_collection,
      )
      # redirect trial keeper's stdout and stderr to syslog
      trial_syslogger_stdout = RemoteLogger(
          args.nnimanager_ip,
          args.nnimanager_port,
          "trial",
          StdOutputType.Stdout,
          args.log_collection,
      )
      sys.stdout = sys.stderr = trial_keeper_syslogger
      hdfs_output_dir = None
  
      if args.hdfs_output_dir:
          hdfs_output_dir = args.hdfs_output_dir
      elif args.pai_hdfs_output_dir:
          hdfs_output_dir = args.pai_hdfs_output_dir
  
      hdfs_client = get_hdfs_client(args)
  
      if hdfs_client is not None:
          copyHdfsDirectoryToLocal(
              args.nni_hdfs_exp_dir, os.getcwd(), hdfs_client
          )
  
      if args.job_id_file:
          with open(args.job_id_file, "w") as job_file:
              job_file.write("%d" % os.getpid())
  
      # Notice: We don't appoint env, which means subprocess wil inherit current environment and that is expected behavior
      log_pipe_stdout = trial_syslogger_stdout.get_pipelog_reader()
      if sys.platform == "win32":
          _trial_process = Popen(
              args.trial_command,
              shell=True,
              stdout=log_pipe_stdout,
              stderr=log_pipe_stdout,
          )
      else:
          _trial_process = Popen(
              args.trial_command,
              shell=True,
              stdout=log_pipe_stdout,
              stderr=log_pipe_stdout,
              preexec_fn=os.setsid,
          )
      nni_log(
          LogType.Info,
          "Trial keeper spawns a subprocess (pid {0}) to run command: {1}".format(
              _trial_process.pid, shlex.split(args.trial_command)
          ),
      )
  
      while True:
          retCode = _trial_process.poll()
          # child worker process exits and all stdout data is read
          if (
              retCode is not None
              and log_pipe_stdout.set_process_exit()
              and log_pipe_stdout.is_read_completed == True
          ):
              # In Windows, the retCode -1 is 4294967295. It's larger than c_long, and raise OverflowError.
              # So covert it to int32.
              retCode = ctypes.c_long(retCode).value
              nni_log(
                  LogType.Info,
                  "subprocess terminated. Exit code is {}. Quit".format(
                      retCode
                  ),
              )
              if hdfs_output_dir is not None:
                  # Copy local directory to hdfs for OpenPAI
                  nni_local_output_dir = os.environ["NNI_OUTPUT_DIR"]
                  try:
                      if copyDirectoryToHdfs(
                          nni_local_output_dir,
                          hdfs_output_dir,
                          hdfs_client,
                      ):
                          nni_log(
                              LogType.Info,
                              "copy directory from {0} to {1} success!".format(
                                  nni_local_output_dir, hdfs_output_dir
                              ),
                          )
                      else:
                          nni_log(
                              LogType.Info,
                              "copy directory from {0} to {1} failed!".format(
                                  nni_local_output_dir, hdfs_output_dir
                              ),
                          )
                  except Exception as e:
                      nni_log(
                          LogType.Error,
                          "HDFS copy directory got exception: "
                          + str(e),
                      )
                      raise e
  
              # Exit as the retCode of subprocess(trial)
              exit(retCode)
              break
  
          time.sleep(2)
  
imports: import argparse
  import ctypes
  import json
  import logging
  import os
  import re
  import shlex
  import sys
  import threading
  import time
  from subprocess import Popen
  import pkg_resources
  from pyhdfs import HdfsClient
  from .constants import LOG_DIR, MULTI_PHASE, NNI_EXP_ID, NNI_PLATFORM, NNI_SYS_DIR, NNI_TRIAL_JOB_ID
  from .hdfsClientUtility import copyDirectoryToHdfs, copyHdfsDirectoryToLocal, copyHdfsFileToLocal
  from .log_utils import LogType, RemoteLogger, StdOutputType, nni_log
  from .rest_utils import rest_get, rest_post
  from .url_utils import gen_parameter_meta_url, gen_send_version_url
label_desc: Use image node_id 2 for calling a global function with example usage: main_loop(args) without return types