From e560933f9c0a8b3b4e6ac62228e8dc401646a021 Mon Sep 17 00:00:00 2001 From: architkulkarni Date: Tue, 12 Jan 2021 09:57:15 -0800 Subject: [PATCH] [Serve] Add dependency management support for driver not running in a conda env (#13269) --- doc/source/serve/advanced.rst | 5 ----- .../ray/serve/examples/doc/imported_backend.py | 1 + python/ray/serve/utils.py | 17 +++++++++++++---- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/doc/source/serve/advanced.rst b/doc/source/serve/advanced.rst index dc386ee11..4ec71103e 100644 --- a/doc/source/serve/advanced.rst +++ b/doc/source/serve/advanced.rst @@ -386,11 +386,6 @@ as shown below. .. literalinclude:: ../../../python/ray/serve/examples/doc/conda_env.py -.. warning:: - The script must be run in an activated conda environment (not required to be - ``ray-tf1`` or ``ray-tf2``). We hope to remove this restriction in the - future. - .. note:: If the argument ``env`` is omitted, backends will be started in the same conda environment as the caller of diff --git a/python/ray/serve/examples/doc/imported_backend.py b/python/ray/serve/examples/doc/imported_backend.py index ec864c211..d80d73b4a 100644 --- a/python/ray/serve/examples/doc/imported_backend.py +++ b/python/ray/serve/examples/doc/imported_backend.py @@ -5,6 +5,7 @@ from ray.serve.backends import ImportedBackend client = serve.start() +# Include your class as input to the ImportedBackend constructor. backend_class = ImportedBackend("ray.serve.utils.MockImportedBackend") client.create_backend("imported", backend_class, "input_arg") client.create_endpoint("imported", backend="imported", route="/imported") diff --git a/python/ray/serve/utils.py b/python/ray/serve/utils.py index 7244ca4db..6d15e53fa 100644 --- a/python/ray/serve/utils.py +++ b/python/ray/serve/utils.py @@ -11,6 +11,7 @@ from typing import Iterable, List, Dict, Tuple import os from ray.serve.exceptions import RayServeException from collections import UserDict +from pathlib import Path import starlette.requests import requests @@ -180,13 +181,21 @@ def format_actor_name(actor_name, controller_name=None, *modifiers): def get_conda_env_dir(env_name): """Given a environment name like `tf1`, find and validate the - corresponding conda directory. + corresponding conda directory. Untested on Windows. """ conda_prefix = os.environ.get("CONDA_PREFIX") if conda_prefix is None: - raise ValueError( - "Serve cannot find environment variables installed by conda. " + - "Are you sure you are in a conda env?") + # The caller is neither in a conda env or in (base). This is rare + # because by default, new terminals start in (base), but we can still + # support this case. + conda_exe = os.environ.get("CONDA_EXE") + if conda_exe is None: + raise RayServeException( + "Ray Serve cannot find environment variables set by conda. " + "Please verify conda is installed.") + # Example: CONDA_EXE=$HOME/anaconda3/bin/python + # Strip out the /bin/python by going up two parent directories. + conda_prefix = str(Path(conda_exe).parent.parent) # There are two cases: # 1. We are in conda base env: CONDA_DEFAULT_ENV=base and