class_docstr: Flavor backend implementation for the generic python models.
docstr: Serve pyfunc model locally.
code: def serve(
      self,
      model_uri,
      port,
      host,
      timeout,
      enable_mlserver,
      synchronous=True,
      stdout=None,
      stderr=None,
  ):
      """
      Serve pyfunc model locally.
      """
      local_path = _download_artifact_from_uri(model_uri)
  
      server_implementation = (
          mlserver if enable_mlserver else scoring_server
      )
      command, command_env = server_implementation.get_cmd(
          local_path, port, host, timeout, self._nworkers
      )
  
      if sys.platform.startswith("linux"):
  
          def setup_sigterm_on_parent_death():
              """
              Uses prctl to automatically send SIGTERM to the command process when its parent is
              dead.
  
              This handles the case when the parent is a PySpark worker process.
              If a user cancels the PySpark job, the worker process gets killed, regardless of
              PySpark daemon and worker reuse settings.
              We use prctl to ensure the command process receives SIGTERM after spark job
              cancellation.
              The command process itself should handle SIGTERM properly.
              This is a no-op on macOS because prctl is not supported.
  
              Note:
              When a pyspark job canceled, the UDF python process are killed by signal "SIGKILL",
              This case neither "atexit" nor signal handler can capture SIGKILL signal.
              prctl is the only way to capture SIGKILL signal.
              """
              try:
                  libc = ctypes.CDLL("libc.so.6")
                  # Set the parent process death signal of the command process to SIGTERM.
                  libc.prctl(
                      1, signal.SIGTERM
                  )  # PR_SET_PDEATHSIG, see prctl.h
              except OSError as e:
                  # TODO: find approach for supporting MacOS/Windows system which does
                  #  not support prctl.
                  warnings.warn(
                      f"Setup libc.prctl PR_SET_PDEATHSIG failed, error {e!r}."
                  )
  
      else:
          setup_sigterm_on_parent_death = None
  
      if _IS_UNIX:
          # Add "exec" before the starting scoring server command, so that the scoring server
          # process replaces the bash process, otherwise the scoring server process is created
          # as a child process of the bash process.
          # Note we in `mlflow.pyfunc.spark_udf`, use prctl PR_SET_PDEATHSIG to ensure scoring
          # server process being killed when UDF process exit. The PR_SET_PDEATHSIG can only
          # send signal to the bash process, if the scoring server process is created as a
          # child process of the bash process, then it cannot receive the signal sent by prctl.
          # TODO: For Windows, there's no equivalent things of Unix shell's exec. Windows also
          #  does not support prctl. We need to find an approach to address it.
          command = "exec " + command
  
      if self._env_manager != _EnvManager.LOCAL:
          return self.prepare_env(local_path).execute(
              command,
              command_env,
              stdout=stdout,
              stderr=stderr,
              preexec_fn=setup_sigterm_on_parent_death,
              synchronous=synchronous,
          )
      else:
          _logger.info("=== Running command '%s'", command)
  
          if os.name != "nt":
              command = ["bash", "-c", command]
  
          child_proc = subprocess.Popen(
              command,
              env=command_env,
              preexec_fn=setup_sigterm_on_parent_death,
              stdout=stdout,
              stderr=stderr,
          )
  
          if synchronous:
              rc = child_proc.wait()
              if rc != 0:
                  raise Exception(
                      f"Command '{command}' returned non zero return code. Return code = {rc}"
                  )
              return 0
          else:
              return child_proc
  
imports: import ctypes
  import logging
  import os
  import pathlib
  import posixpath
  import shlex
  import signal
  import subprocess
  import sys
  import warnings
  from pathlib import Path
  from mlflow.environment_variables import MLFLOW_DISABLE_ENV_CREATION
  from mlflow.exceptions import MlflowException
  from mlflow.models import FlavorBackend
  from mlflow.models.container import ENABLE_MLSERVER
  from mlflow.models.docker_utils import SETUP_MINICONDA, SETUP_PYENV_AND_VIRTUALENV, _build_image, _generate_dockerfile_content, _get_mlflow_install_step
  from mlflow.pyfunc import ENV, _extract_conda_env, _mlflow_pyfunc_backend_predict, mlserver, scoring_server
  from mlflow.tracking.artifact_utils import _download_artifact_from_uri
  from mlflow.utils import env_manager
  from mlflow.utils.conda import get_conda_bin_executable, get_or_create_conda_env
  from mlflow.utils.environment import Environment
  from mlflow.utils.file_utils import get_or_create_nfs_tmp_dir, get_or_create_tmp_dir, path_to_local_file_uri
  from mlflow.utils.nfs_on_spark import get_nfs_cache_root_dir
  from mlflow.utils.process import ShellCommandException, cache_return_value_per_process
  from mlflow.utils.virtualenv import _get_or_create_virtualenv, _get_pip_install_mlflow
  from mlflow.version import VERSION
label_desc: Use image node_id 4 for calling the PyFuncBackend obj's underlying member method code with example usage: obj.serve(model_uri, port, host, timeout, enable_mlserver, synchronous, stdout, stderr) and returns: self, int, child_proc