class_docstr: Launcher is the main entrance of nodes in TFleX.
  
  It handles TFX internal details like artifact resolving, execution
  triggering and result publishing.
class_docstr_tok: ["Launcher","is","the","main","entrance","of","nodes","in","TFleX",".","It","handles","TFX","internal","details","like","artifact","resolving",",","execution","triggering","and","result","publishing","."]
docstr: Executes the component, includes driver, executor and publisher.
  
  Returns:
    The metadata of this execution that is registered in MLMD. It can be None
    if the driver decides not to run the execution.
  
  Raises:
    Exception: If the executor fails.
code: def launch(self) -> Optional[data_types.ExecutionInfo]:
      """Executes the component, includes driver, executor and publisher.
  
      Returns:
        The metadata of this execution that is registered in MLMD. It can be None
        if the driver decides not to run the execution.
  
      Raises:
        Exception: If the executor fails.
      """
      logging.info("Running launcher for %s", self._pipeline_node)
      if self._system_node_handler:
          # If this is a system node, runs it and directly return.
          return self._system_node_handler.run(
              self._mlmd_connection,
              self._pipeline_node,
              self._pipeline_info,
              self._pipeline_runtime_spec,
          )
  
      # Runs as a normal node.
      execution_preparation_result = self._prepare_execution()
      execution_info = execution_preparation_result.execution_info
      contexts = execution_preparation_result.contexts
      is_execution_needed = (
          execution_preparation_result.is_execution_needed
      )
      if is_execution_needed:
          executor_watcher = None
          try:
              if self._executor_operator:
                  # Create an execution watcher and save an in memory copy of the
                  # Execution object to execution to it. Launcher calls executor
                  # operator in process, thus there won't be race condition between the
                  # execution watcher and the launcher to write to MLMD.
                  executor_watcher = execution_watcher.ExecutionWatcher(
                      port=portpicker.pick_unused_port(),
                      mlmd_connection=self._mlmd_connection,
                      execution=execution_preparation_result.execution_metadata,
                      creds=grpc.local_server_credentials(),
                  )
                  self._executor_operator.with_execution_watcher(
                      executor_watcher.address
                  )
                  executor_watcher.start()
              executor_output = self._run_executor(execution_info)
          except Exception as e:  # pylint: disable=broad-except
              execution_output = (
                  e.executor_output
                  if isinstance(e, _ExecutionFailedError)
                  else None
              )
              self._publish_failed_execution(
                  execution_info.execution_id,
                  contexts,
                  execution_output,
              )
              logging.error(
                  "Execution %d failed.", execution_info.execution_id
              )
              raise
          finally:
              self._clean_up_stateless_execution_info(execution_info)
              if executor_watcher:
                  executor_watcher.stop()
  
          logging.info(
              "Execution %d succeeded.", execution_info.execution_id
          )
          self._clean_up_stateful_execution_info(execution_info)
  
          logging.info(
              "Publishing output artifacts %s for execution %s",
              execution_info.output_dict,
              execution_info.execution_id,
          )
          self._publish_successful_execution(
              execution_info.execution_id,
              contexts,
              execution_info.output_dict,
              executor_output,
          )
      return execution_info
  
imports: import sys
  from typing import Any, Dict, List, Mapping, Optional, Type, TypeVar
  from absl import logging
  import attr
  import grpc
  import portpicker
  from tfx import types
  from tfx.dsl.compiler import placeholder_utils
  from tfx.dsl.io import fileio
  from tfx.orchestration import data_types_utils
  from tfx.orchestration import metadata
  from tfx.orchestration.portable import base_driver_operator
  from tfx.orchestration.portable import base_executor_operator
  from tfx.orchestration.portable import beam_executor_operator
  from tfx.orchestration.portable import cache_utils
  from tfx.orchestration.portable import data_types
  from tfx.orchestration.portable import docker_executor_operator
  from tfx.orchestration.portable import execution_publish_utils
  from tfx.orchestration.portable import execution_watcher
  from tfx.orchestration.portable import importer_node_handler
  from tfx.orchestration.portable import inputs_utils
  from tfx.orchestration.portable import outputs_utils
  from tfx.orchestration.portable import python_driver_operator
  from tfx.orchestration.portable import python_executor_operator
  from tfx.orchestration.portable import resolver_node_handler
  from tfx.orchestration.portable.input_resolution import exceptions
  from tfx.orchestration.portable.mlmd import context_lib
  from tfx.orchestration.portable.mlmd import execution_lib
  from tfx.proto.orchestration import driver_output_pb2
  from tfx.proto.orchestration import executable_spec_pb2
  from tfx.proto.orchestration import execution_result_pb2
  from tfx.proto.orchestration import pipeline_pb2
  from tfx.utils import typing_utils
  from google.protobuf import message
  from ml_metadata.proto import metadata_store_pb2
label_desc: Use image node_id 12 for calling the Launcher obj's underlying member method code with example usage: obj.launch() and returns: execution_info, self