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: Method for getting or creating an experiment. It will try to first get a valid experiment, if exception occurs, it will
  automatically create a new experiment based on the given id and name.
code: def _get_or_create_exp(
      self, experiment_id=None, experiment_name=None
  ) -> (object, bool):
      """
      Method for getting or creating an experiment. It will try to first get a valid experiment, if exception occurs, it will
      automatically create a new experiment based on the given id and name.
      """
      try:
          return (
              self._get_exp(
                  experiment_id=experiment_id,
                  experiment_name=experiment_name,
              ),
              False,
          )
      except ValueError:
          if experiment_name is None:
              experiment_name = self._default_exp_name
          logger.warning(
              f"No valid experiment found. Create a new experiment with name {experiment_name}."
          )
  
          # NOTE: mlflow doesn't consider the lock for recording multiple runs
          # So we supported it in the interface wrapper
          pr = urlparse(self.uri)
          if pr.scheme == "file":
              with FileLock(
                  os.path.join(pr.netloc, pr.path, "filelock")
              ):  # pylint: disable=E0110
                  return self.create_exp(experiment_name), True
          # NOTE: for other schemes like http, we double check to avoid create exp conflicts
          try:
              return self.create_exp(experiment_name), True
          except ExpAlreadyExistError:
              return (
                  self._get_exp(
                      experiment_id=experiment_id,
                      experiment_name=experiment_name,
                  ),
                  False,
              )
  
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 10 for calling the ExpManager obj's underlying member method code with example usage: obj._get_or_create_exp(experiment_id, experiment_name) and returns: self,  False, self,  True, self,  True, self,  False