Repository: microsoft/qlib
File: qlib/workflow/expm.py (Python)

Code before:
    def end_exp(self, recorder_status: Text = Recorder.STATUS_S):
        if self.active_experiment is not None:
            self.active_experiment.end(recorder_status)
            self.active_experiment = None
        # When an experiment end, we will release the current uri.
        self._current_uri = None

    def create_exp(self, experiment_name: Optional[Text] = None):
        assert experiment_name is not None
        # init experiment
        experiment_id = self.client.create_experiment(experiment_name)
        experiment = MLflowExperiment(experiment_id, experiment_name, self.uri)
        experiment._default_name = self._default_exp_name

        return experiment

    def _get_exp(self, experiment_id=None, experiment_name=None):
        """
        Method for getting or creating an experiment. It will try to first get a valid experiment, if exception occurs, it will
        raise errors.
        """
        assert (
            experiment_id is not None or experiment_name is not None
        ), "Please input at least one of experiment/recorder id or name before retrieving experiment/recorder."
        if experiment_id is not None:
            try:
                experiment_id = int(experiment_id)
            except ValueError as e:
                msg = "The `experiment_id` for mlflow backend must be `int`"
                logger.error(msg)
                # We have to raise type error here
                # - The error looks like type error
                # - Value Error will be catched
                raise TypeError(msg)
            try:
                exp = self.client.get_experiment(experiment_id)
                if exp.lifecycle_stage.upper() == "DELETED":
                    raise MlflowException("No valid experiment has been found.")
                experiment = MLflowExperiment(exp.experiment_id, exp.name, self.uri)
                return experiment
            except MlflowException:
                raise ValueError(
                    "No valid experiment has been found, please make sure the input experiment id is correct."
                )
        elif experiment_name is not None:
            try:
                exp = self.client.get_experiment_by_name(experiment_name)
                if exp is None or exp.lifecycle_stage.upper() == "DELETED":
                    raise MlflowException("No valid experiment has been found.")
                experiment = MLflowExperiment(exp.experiment_id, experiment_name, self.uri)
                return experiment

Review comment (suggestion):
I feel like this is a little bit redundant? If the user inputs an invalid experiment id, then mlflow will not find the corresponding experiment and we will raise an `MlflowException` in the following codes (under the `except` [here](https://github.com/microsoft/qlib/blob/d4b36bdab448859f04b163b89843594660b3323f/qlib/workflow/expm.py#L369)).

Instead, we could update the `MlflowException` error messages, which tells the user that the id of an experiment should be `int` or `str` of int.

Code after:
    def end_exp(self, recorder_status: Text = Recorder.STATUS_S):
        if self.active_experiment is not None:
            self.active_experiment.end(recorder_status)
            self.active_experiment = None
        # When an experiment end, we will release the current uri.
        self._current_uri = None

    def create_exp(self, experiment_name: Optional[Text] = None):
        assert experiment_name is not None
        # init experiment
        experiment_id = self.client.create_experiment(experiment_name)
        experiment = MLflowExperiment(experiment_id, experiment_name, self.uri)
        experiment._default_name = self._default_exp_name

        return experiment

    def _get_exp(self, experiment_id=None, experiment_name=None):
        """
        Method for getting or creating an experiment. It will try to first get a valid experiment, if exception occurs, it will
        raise errors.
        """
        assert (
            experiment_id is not None or experiment_name is not None
        ), "Please input at least one of experiment/recorder id or name before retrieving experiment/recorder."
        if experiment_id is not None:
            try:
                # NOTE: the mlflow's experiment_id must be str type...
                # https://www.mlflow.org/docs/latest/python_api/mlflow.tracking.html#mlflow.tracking.MlflowClient.get_experiment
                exp = self.client.get_experiment(experiment_id)
                if exp.lifecycle_stage.upper() == "DELETED":
                    raise MlflowException("No valid experiment has been found.")
                experiment = MLflowExperiment(exp.experiment_id, exp.name, self.uri)
                return experiment
            except MlflowException:
                raise ValueError(
                    "No valid experiment has been found, please make sure the input experiment id is correct."
                )
        elif experiment_name is not None:
            try:
                exp = self.client.get_experiment_by_name(experiment_name)
                if exp is None or exp.lifecycle_stage.upper() == "DELETED":
                    raise MlflowException("No valid experiment has been found.")
                experiment = MLflowExperiment(exp.experiment_id, experiment_name, self.uri)
                return experiment
            except MlflowException as e:
                raise ValueError(
                    "No valid experiment has been found, please make sure the input experiment name is correct."
                )

    def search_records(self, experiment_ids, **kwargs):
        filter_string = "" if kwargs.get("filter_string") is None else kwargs.get("filter_string")