class_docstr: This is the `ExpManager` class for managing experiments. The API is designed similar to mlflow.
  (The link: https://mlflow.org/docs/latest/python_api/mlflow.html)
  
  The `ExpManager` is expected to be a singleton (btw, we can have multiple `Experiment`s with different uri. user can get different experiments from different uri, and then compare records of them). Global Config (i.e. `C`)  is also a singleton.
  
  So we try to align them together.  They share the same variable, which is called **default uri**. Please refer to `ExpManager.default_uri` for details of variable sharing.
  
  When the user starts an experiment, the user may want to set the uri to a specific uri (it will override **default uri** during this period), and then unset the **specific uri** and fallback to the **default uri**.    `ExpManager._active_exp_uri` is that **specific uri**.
docstr: Retrieve an experiment. This method includes getting an active experiment, and get_or_create a specific experiment.
  
  When user specify experiment id and name, the method will try to return the specific experiment.
  When user does not provide recorder id or name, the method will try to return the current active experiment.
  The `create` argument determines whether the method will automatically create a new experiment according
  to user's specification if the experiment hasn't been created before.
  
  * If `create` is True:
  
      * If `active experiment` exists:
  
          * no id or name specified, return the active experiment.
          * if id or name is specified, return the specified experiment. If no such exp found, create a new experiment with given id or name. If `start` is set to be True, the experiment is set to be active.
  
      * If `active experiment` not exists:
  
          * no id or name specified, create a default experiment.
          * if id or name is specified, return the specified experiment. If no such exp found, create a new experiment with given id or name. If `start` is set to be True, the experiment is set to be active.
  
  * Else If `create` is False:
  
      * If `active experiment` exists:
  
          * no id or name specified, return the active experiment.
          * if id or name is specified, return the specified experiment. If no such exp found, raise Error.
  
      * If `active experiment` not exists:
  
          *  no id or name specified. If the default experiment exists, return it, otherwise, raise Error.
          * if id or name is specified, return the specified experiment. If no such exp found, raise Error.
  
  Parameters
  ----------
  experiment_id : str
      id of the experiment to return.
  experiment_name : str
      name of the experiment to return.
  create : boolean
      create the experiment it if hasn't been created before.
  start : boolean
      start the new experiment if one is created.
  
  Returns
  -------
  An experiment object.
code: def get_exp(
      self,
      *,
      experiment_id=None,
      experiment_name=None,
      create: bool = True,
      start: bool = False,
  ):
      """
      Retrieve an experiment. This method includes getting an active experiment, and get_or_create a specific experiment.
  
      When user specify experiment id and name, the method will try to return the specific experiment.
      When user does not provide recorder id or name, the method will try to return the current active experiment.
      The `create` argument determines whether the method will automatically create a new experiment according
      to user's specification if the experiment hasn't been created before.
  
      * If `create` is True:
  
          * If `active experiment` exists:
  
              * no id or name specified, return the active experiment.
              * if id or name is specified, return the specified experiment. If no such exp found, create a new experiment with given id or name. If `start` is set to be True, the experiment is set to be active.
  
          * If `active experiment` not exists:
  
              * no id or name specified, create a default experiment.
              * if id or name is specified, return the specified experiment. If no such exp found, create a new experiment with given id or name. If `start` is set to be True, the experiment is set to be active.
  
      * Else If `create` is False:
  
          * If `active experiment` exists:
  
              * no id or name specified, return the active experiment.
              * if id or name is specified, return the specified experiment. If no such exp found, raise Error.
  
          * If `active experiment` not exists:
  
              *  no id or name specified. If the default experiment exists, return it, otherwise, raise Error.
              * if id or name is specified, return the specified experiment. If no such exp found, raise Error.
  
      Parameters
      ----------
      experiment_id : str
          id of the experiment to return.
      experiment_name : str
          name of the experiment to return.
      create : boolean
          create the experiment it if hasn't been created before.
      start : boolean
          start the new experiment if one is created.
  
      Returns
      -------
      An experiment object.
      """
      # special case of getting experiment
      if experiment_id is None and experiment_name is None:
          if self.active_experiment is not None:
              return self.active_experiment
          # User don't want get active code now.
          experiment_name = self._default_exp_name
  
      if create:
          exp, _ = self._get_or_create_exp(
              experiment_id=experiment_id,
              experiment_name=experiment_name,
          )
      else:
          exp = self._get_exp(
              experiment_id=experiment_id,
              experiment_name=experiment_name,
          )
      if self.active_experiment is None and start:
          self.active_experiment = exp
          # start the recorder
          self.active_experiment.start()
      return exp
  
imports: from urllib.parse import urlparse
  import mlflow
  from filelock import FileLock
  from mlflow.exceptions import MlflowException, RESOURCE_ALREADY_EXISTS, ErrorCode
  from mlflow.entities import ViewType
  import os
  from typing import Optional, Text
  from .exp import MLflowExperiment, Experiment
  from ..config import C
  from .recorder import Recorder
  from ..log import get_module_logger
  from ..utils.exceptions import ExpAlreadyExistError
label_desc: Use image node_id 9 for calling the ExpManager obj's underlying member method code with example usage: obj.get_exp() and returns: exp, self