From 779b1786bdd18b42b88b2ef6f0c28eee21d547b3 Mon Sep 17 00:00:00 2001 From: you-n-g Date: Tue, 16 Nov 2021 11:43:35 +0800 Subject: [PATCH] Merging Backtest improve (#694) * Fix private import * temporarily fix create exp conflicts for remote mlflow Co-authored-by: Dong Zhou --- qlib/utils/exceptions.py | 6 ++++++ qlib/workflow/expm.py | 25 +++++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/qlib/utils/exceptions.py b/qlib/utils/exceptions.py index dd9b3eaf6..ed9d567be 100644 --- a/qlib/utils/exceptions.py +++ b/qlib/utils/exceptions.py @@ -18,3 +18,9 @@ class LoadObjectError(QlibException): """Error type for Recorder when can not load object""" pass + + +class ExpAlreadyExistError(Exception): + """Experiment already exists""" + + pass diff --git a/qlib/workflow/expm.py b/qlib/workflow/expm.py index 5d3596c4d..9efbc5b06 100644 --- a/qlib/workflow/expm.py +++ b/qlib/workflow/expm.py @@ -4,7 +4,7 @@ from urllib.parse import urlparse import mlflow from filelock import FileLock -from mlflow.exceptions import MlflowException +from mlflow.exceptions import MlflowException, RESOURCE_ALREADY_EXISTS, ErrorCode from mlflow.entities import ViewType import os, logging from pathlib import Path @@ -15,6 +15,7 @@ from .exp import MLflowExperiment, Experiment from ..config import C from .recorder import Recorder from ..log import get_module_logger +from ..utils.exceptions import ExpAlreadyExistError logger = get_module_logger("workflow", logging.INFO) @@ -94,6 +95,10 @@ class ExpManager: Returns ------- An experiment object. + + Raise + ----- + ExpAlreadyExistError """ raise NotImplementedError(f"Please implement the `create_exp` method.") @@ -200,7 +205,14 @@ class ExpManager: if pr.scheme == "file": with FileLock(os.path.join(pr.netloc, pr.path, "filelock")) as f: return self.create_exp(experiment_name), True - 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, + ) def _get_exp(self, experiment_id=None, experiment_name=None) -> Experiment: """ @@ -345,10 +357,15 @@ class MLflowExpManager(ExpManager): 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) + try: + experiment_id = self.client.create_experiment(experiment_name) + except MlflowException as e: + if e.error_code == ErrorCode.Name(RESOURCE_ALREADY_EXISTS): + raise ExpAlreadyExistError() + raise e + 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):