环境依赖#
您的 Ray 应用可能在 Ray 脚本之外存在一些依赖项。例如:
您的 Ray 脚本可能导入/依赖某些 Python 包。
您的 Ray 脚本可能需要某些特定的环境变量可用。
您的 Ray 脚本可能导入脚本之外的某些文件。
在集群上运行时,一个常见的问题是 Ray 希望这些“依赖项”存在于每个 Ray 节点上。如果这些依赖项不存在,您可能会遇到诸如 ModuleNotFoundError、FileNotFoundError 等问题。
为了解决这个问题,您可以(1)预先在集群上准备好您的依赖项(例如使用容器镜像),方法是使用 Ray 的 集群启动器,或者(2)使用 Ray 的 运行时环境 动态安装它们。
对于生产环境或不变的环境,我们建议将依赖项安装到容器镜像中,并通过集群启动器指定该镜像。对于动态环境(例如用于开发和实验),我们建议使用运行时环境。
概念#
Ray 应用。一个包含 Ray 脚本的程序,该脚本调用
ray.init()并使用 Ray 任务或 actor。依赖项或环境。您的应用程序运行所需的 Ray 脚本之外的任何内容,包括文件、包和环境变量。
文件。您的 Ray 应用程序运行所需的代码文件、数据文件或其他文件。
包。您的 Ray 应用程序所需的外部库或可执行文件,通常通过
pip或conda安装。本地机器和集群。通常,您可能希望将 Ray 集群的计算机器/Pod 与处理和提交应用程序的机器/Pod 分开。您可以通过 Ray 作业提交机制 提交 Ray 作业,或使用
ray attach交互式连接到集群。我们将提交作业的机器称为您的本地机器。作业。一个 Ray 作业 是一个单一的应用程序:它是由同一脚本产生的 Ray 任务、对象和 actor 的集合。
使用 Ray 集群启动器准备环境#
设置依赖项的第一种方法是在启动 Ray 运行时之前,在整个集群上准备一个统一的环境。
您可以将所有文件和依赖项构建到容器镜像中,并在您的 集群 YAML 配置 中指定此镜像。
您还可以使用 Ray 集群配置文件中的
setup_commands来安装包(请参阅 参考);这些命令将在每个节点加入集群时运行。请注意,对于生产环境,建议将任何必需的包构建到容器镜像中。您可以使用
ray rsync_up将本地文件推送到集群(请参阅 参考)。
运行时环境#
注意
此功能需要通过 pip install "ray[default]" 全面安装 Ray。此功能自 Ray 1.4.0 起可用,目前支持 macOS 和 Linux,并在 Windows 上提供 Beta 支持。
设置依赖项的第二种方法是在 Ray 运行时动态安装它们。
运行时环境描述了您的 Ray 应用程序运行所需的依赖项,包括 文件、包、环境变量等。它会在运行时动态安装在集群上,并缓存以备将来使用(有关生命周期的详细信息,请参阅 缓存和垃圾回收)。
如果使用了 Ray 集群启动器,则可以在其准备好的环境之上使用运行时环境。例如,您可以使用集群启动器安装一组基础包,然后使用运行时环境安装其他包。与基础集群环境相比,运行时环境仅对 Ray 进程有效。(例如,如果使用指定 pip 包 my_pkg 的运行时环境,则在 Ray 任务、actor 或作业之外调用语句 import my_pkg 将会失败。)
运行时环境还允许您在长期运行的 Ray 集群上为每个任务、每个 actor 和每个作业设置依赖项。
import ray
runtime_env = {"pip": ["emoji"]}
ray.init(runtime_env=runtime_env)
@ray.remote
def f():
import emoji
return emoji.emojize('Python is :thumbs_up:')
print(ray.get(f.remote()))
Python is 👍
运行时环境可以由 Python dict 描述
runtime_env = {
"pip": ["emoji"],
"env_vars": {"TF_WARNINGS": "none"}
}
或者,您可以使用 ray.runtime_env.RuntimeEnv
from ray.runtime_env import RuntimeEnv
runtime_env = RuntimeEnv(
pip=["emoji"],
env_vars={"TF_WARNINGS": "none"}
)
有关更多示例,请跳转到 API 参考。
您可以为以下两个主要范围指定运行时环境:
为每个作业指定运行时环境#
您可以为整个作业指定运行时环境,无论是在集群上直接运行脚本、使用 Ray 作业 API,还是提交 KubeRay 作业。
# Option 1: Starting a single-node local Ray cluster or connecting to existing local cluster
ray.init(runtime_env=runtime_env)
# Option 2: Using Ray Jobs API (Python SDK)
from ray.job_submission import JobSubmissionClient
client = JobSubmissionClient("http://<head-node-ip>:8265")
job_id = client.submit_job(
entrypoint="python my_ray_script.py",
runtime_env=runtime_env,
)
# Option 3: Using Ray Jobs API (CLI). (Note: can use --runtime-env to pass a YAML file instead of an inline JSON string.)
$ ray job submit --address="http://<head-node-ip>:8265" --runtime-env-json='{"working_dir": "/data/my_files", "pip": ["emoji"]}' -- python my_ray_script.py
# Option 4: Using KubeRay RayJob. You can specify the runtime environment in the RayJob YAML manifest.
# [...]
spec:
runtimeEnvYAML: |
pip:
- requests==2.26.0
- pendulum==2.1.2
env_vars:
KEY: "VALUE"
警告
在 submit_job 或 ray job submit 调用中指定 runtime_env 参数,可确保在入口脚本运行之前,运行时环境已安装在集群上。
如果 runtime_env 是从 ray.init(runtime_env=...) 指定的,则运行时环境仅应用于所有子任务和 actor,而不应用于入口脚本(驱动程序)本身。
如果 runtime_env 同时由 ray job submit 和 ray.init 指定,则运行时环境将合并。有关详细信息,请参阅 由作业和驱动程序同时指定的运行时环境。
注意
安装运行时环境有两种选项:
在作业启动时立即安装(即,在调用
ray.init()后立即),依赖项将被急切地下载和安装。仅在调用任务或创建 actor 时安装依赖项。
默认选项是选项 1。要将行为更改为选项 2,请在 runtime_env 的 config 中添加 "eager_install": False。
为每个任务或 actor 指定运行时环境#
您可以使用 .options() 或 @ray.remote 装饰器为每个 actor 或每个任务指定不同的运行时环境。
# Invoke a remote task that will run in a specified runtime environment.
f.options(runtime_env=runtime_env).remote()
# Instantiate an actor that will run in a specified runtime environment.
actor = SomeClass.options(runtime_env=runtime_env).remote()
# Specify a runtime environment in the task definition. Future invocations via
# `g.remote()` will use this runtime environment unless overridden by using
# `.options()` as above.
@ray.remote(runtime_env=runtime_env)
def g():
pass
# Specify a runtime environment in the actor definition. Future instantiations
# via `MyClass.remote()` will use this runtime environment unless overridden by
# using `.options()` as above.
@ray.remote(runtime_env=runtime_env)
class MyClass:
pass
这使您可以让 actor 和任务在各自独立于周围环境的环境中运行。(周围环境可以是作业的运行时环境,也可以是集群的系统环境。)
警告
Ray 不保证具有冲突运行时环境的任务和 actor 之间的兼容性。例如,如果一个运行时环境包含 pip 包的 actor 尝试与具有不同版本该包的 actor 通信,则可能导致意外行为,例如反序列化错误。
常见工作流程#
本节描述了运行时环境的一些常见用例。这些用例并非互斥;下面描述的所有选项都可以在单个运行时环境中组合使用。
使用本地文件#
您的 Ray 应用程序可能依赖于源文件或数据文件。对于开发工作流程,这些文件可能位于您的本地机器上,但当需要大规模运行时,您需要将它们传输到您的远程集群。
下面的简单示例说明了如何将本地文件传输到集群。
import os
import ray
os.makedirs("/tmp/runtime_env_working_dir", exist_ok=True)
with open("/tmp/runtime_env_working_dir/hello.txt", "w") as hello_file:
hello_file.write("Hello World!")
# Specify a runtime environment for the entire Ray job
ray.init(runtime_env={"working_dir": "/tmp/runtime_env_working_dir"})
# Create a Ray task, which inherits the above runtime env.
@ray.remote
def f():
# The function will have its working directory changed to its node's
# local copy of /tmp/runtime_env_working_dir.
return open("hello.txt").read()
print(ray.get(f.remote()))
Hello World!
注意
上面的示例是为在本地机器上运行而编写的,但与所有这些示例一样,它在指定要连接的 Ray 集群时(例如,使用 ray.init("ray://123.456.7.89:10001", runtime_env=...) 或 ray.init(address="auto", runtime_env=...))也适用。
指定的本地目录将在调用 ray.init() 时自动推送到集群节点。
您还可以通过远程云存储 URI 指定文件;有关详细信息,请参阅 远程 URI。
如果您指定了 working_dir,Ray 总是会先准备它,并且它会在创建其他运行时环境时存在于 ${RAY_RUNTIME_ENV_CREATE_WORKING_DIR} 环境变量中。这种顺序允许 pip 和 conda 引用 working_dir 中的本地文件,例如 requirements.txt 或 environment.yml。有关更多详细信息,请参阅 API 参考 中的 pip 和 conda 部分。
使用 conda 或 pip 包#
您的 Ray 应用程序可能通过 import 语句依赖 Python 包(例如,pendulum 或 requests)。
Ray 通常期望所有导入的包都已预先安装在集群的每个节点上;特别是,这些包不会自动从您的本地机器传输到集群,也不会从任何存储库下载。
但是,通过运行时环境,您可以动态指定要在 Ray 作业或特定 Ray 任务或 actor 的虚拟环境中自动下载和安装的包。
import ray
import requests
# This example runs on a local machine, but you can also do
# ray.init(address=..., runtime_env=...) to connect to a cluster.
ray.init(runtime_env={"pip": ["requests"]})
@ray.remote
def reqs():
return requests.get("https://rayai.org.cn/").status_code
print(ray.get(reqs.remote()))
200
您还可以通过 Python 列表或本地 requirements.txt 文件指定您的 pip 依赖项。当您的 pip install 命令需要 --extra-index-url 或 --find-links 等选项时,请考虑指定 requirements.txt 文件;有关详细信息,请参阅 https://pip.pypa.org.cn/en/stable/reference/requirements-file-format/#。或者,您可以指定一个 conda 环境,可以是通过 Python 字典或本地 environment.yml 文件。此 conda 环境可以包含 pip 包。有关详细信息,请转到 API 参考。
警告
由于 runtime_env 中的包是在运行时安装的,因此在指定涉及从源代码构建的 conda 或 pip 包时要谨慎,因为这可能很慢。
注意
当使用 "pip" 字段时,指定的包将使用 virtualenv “安装在”基础环境之上,因此您集群上已有的包仍然可以导入。相反,当使用 conda 字段时,您的 Ray 任务和 actor 将在一个隔离的环境中运行。conda 和 pip 字段不能同时用于单个 runtime_env。
注意
本身 ray[default] 包将自动安装到环境中。仅对于 conda 字段,如果您使用任何其他 Ray 库(例如 Ray Serve),则需要在运行时环境中指定该库(例如 runtime_env = {"conda": {"dependencies": ["pytorch", "pip", {"pip": ["requests", "ray[serve]"]}]}})。
注意
conda 环境必须具有与 Ray 集群相同的 Python 版本。请勿在 conda 依赖项中列出 ray,因为它将自动安装。
使用 uv 进行包管理#
在运行时环境中,使用 uv 进行包管理的推荐方法是通过 uv run。
此方法提供了几个关键优势:首先,它使驱动程序和 Ray 工作进程之间的依赖项保持同步。此外,它完全支持 pyproject.toml,包括可编辑包。它还允许您使用 uv lock 锁定包版本。有关更多详细信息,请参阅 UV 脚本文档 以及 我们的博客文章。
在工作目录中创建一个类似下面的 pyproject.toml 文件:
[project]
name = "test"
version = "0.1"
dependencies = [
"emoji",
"ray",
]
然后创建一个类似下面的 test.py 文件:
import emoji
import ray
@ray.remote
def f():
return emoji.emojize('Python is :thumbs_up:')
# Execute 1000 copies of f across a cluster.
print(ray.get([f.remote() for _ in range(1000)]))
并使用 uv run test.py 运行驱动脚本。这将跨 Ray 集群中的多个 Python 工作进程运行 f 函数的 1000 个副本。除了对主脚本可用外,emoji 依赖项也对所有工作进程可用。此外,当前工作目录中的源代码对所有工作进程都可用。
此工作流程还支持可编辑包,例如,您可以使用 uv add --editable ./path/to/package,其中 ./path/to/package 必须位于当前工作目录中,以便所有工作进程都能访问。
有关如何使用 uv run 运行带有 Ray Data 的批处理推理工作负载的端到端示例,请参阅 此处。
在 Ray 作业中使用 uv:使用与上面相同的 pyproject.toml 和 test.py 文件,您可以通过以下方式提交 Ray 作业:
ray job submit --working-dir . -- uv run test.py
此命令可确保作业的驱动程序和工作进程都在您的 pyproject.toml 指定的 uv 环境中运行。
将 uv 与 Ray Serve 结合使用:使用适当的 pyproject.toml 和 app.py 文件,您可以使用 uv run serve run app:main 运行 Ray Serve 应用程序。
最佳实践和技巧
如果您在 Ray 集群上运行,您的 uv 环境的 Ray 和 Python 版本必须与您的集群的 Ray 和 Python 版本相同,否则您将收到版本不匹配的异常。有多种方法可以解决此问题:
如果您使用的是临时 Ray 集群,请在具有正确版本的集群上运行应用程序。
如果您需要在不同版本的集群上运行,请考虑通过更新
pyproject.toml文件或使用uv run的--active标志(即uv run --active main.py)来修改 uv 环境的版本。
使用
uv lock生成锁文件,并确保所有依赖项都被锁定,这样在发布新版本包时,就不会发生不受控制的变化。如果您有一个 requirements.txt 文件,可以使用
uv add -r requirement.txt将依赖项添加到您的pyproject.toml文件中,然后与 uv run 一起使用。如果您的
pyproject.toml位于某个子目录中,您可以使用uv run --project从那里使用它。如果您使用 uv run 并希望将工作目录重置为非当前工作目录,请使用
--directory标志。Ray uv 集成确保您的working_dir被相应地设置。
高级用例: 在底层,uv run 支持是通过一个名为 py_executable 的低级运行时环境插件实现的。它允许您指定 Ray 工作进程将在其中运行的可执行文件(包括参数)。对于 uv,py_executable 被设置为 uv run,并带有运行驱动程序时使用的相同参数。此外,working_dir 运行时环境用于将驱动程序的目录(包括 pyproject.toml)传播到工作进程。这使得 uv 能够为工作进程设置正确的依赖项和环境。在某些高级用例中,您可能希望直接在程序中使用 py_executable 机制。
具有异构依赖项的应用程序: Ray 支持为不同的任务或 actor 使用不同的运行时环境。这对于在不同的 Ray Serve 部署中部署不同的推理引擎、模型或微服务,以及用于 Ray Data 中的异构数据管道非常有用。要实现这一点,您可以为每个运行时环境指定一个不同的
py_executable,并为每个环境使用带有不同--project参数的 uv run。或者,您也可以为每个环境使用不同的working_dir。自定义工作进程运行的命令: 在工作进程上,您可能希望使用一些驱动程序未使用的特殊参数来自定义 uv。或者,您可能希望使用
poetry run、构建系统(如 bazel)、性能分析器或调试器来运行进程。在这些情况下,您可以通过py_executable显式指定工作进程应运行的可执行文件。如果它是存储在working_dir中的 shell 脚本,以便您以更复杂的方式包装多个进程。
注意
uv 环境将由所有子任务和 actor 继承。如果您想混合环境,例如,将 pip 运行时环境与 uv run 混合使用,您需要将 Python 可执行文件设置回一个不在隔离的 uv 环境中运行的可执行文件,如下所示:
[project]
name = "test"
version = "0.1"
dependencies = [
"emoji",
"ray",
"pip",
"virtualenv",
]
import ray
@ray.remote(runtime_env={"pip": ["wikipedia"], "py_executable": "python"})
def f():
import wikipedia
return wikipedia.summary("Wikipedia")
@ray.remote
def g():
import emoji
return emoji.emojize('Python is :thumbs_up:')
print(ray.get(f.remote()))
print(ray.get(g.remote()))
虽然上述模式可能有助于支持旧版应用程序,但 Ray 团队建议也使用 uv 来跟踪嵌套环境。您可以通过创建一个包含嵌套环境依赖项的单独 pyproject.toml 文件来使用此方法。
库开发#
假设您正在 Ray 上开发一个名为 my_module 的库。
典型的迭代周期将包括:
对
my_module的源代码进行一些更改。运行 Ray 脚本来测试更改,可能是在分布式集群上。
为确保您的本地更改在所有 Ray 工作进程中显示并可以正确导入,请使用 py_modules 字段。
import ray
import my_module
ray.init("ray://123.456.7.89:10001", runtime_env={"py_modules": [my_module]})
@ray.remote
def test_my_module():
# No need to import my_module inside this function.
my_module.test()
ray.get(test_my_module.remote())
API 参考#
The runtime_env 是一个 Python 字典或 Python 类 ray.runtime_env.RuntimeEnv,包含以下一个或多个字段:
working_dir(str):指定 Ray 工作进程的工作目录。它必须是(1)一个本地存在的目录,总大小不超过 500 MiB,(2)一个本地存在的 zip 文件,解压后的总大小不超过 500 MiB(注意:《excludes》无效),或(3)一个指向远程存储的 zip 文件的 URI,该 zip 文件包含作业的工作目录(Ray 不强制执行文件大小限制)。有关详细信息,请参阅 远程 URI。指定的目录将被下载到集群的每个节点上,Ray 工作进程将在其节点上的该目录副本中启动。示例
"." # 当前工作目录"/src/my_project""/src/my_project.zip""s3://path/to/my_dir.zip"
注意:目前不支持为每个任务或 actor 设置本地目录;它只能为每个作业设置(即在
ray.init()中)。注意:默认情况下,如果本地目录包含
.gitignore和/或.rayignore文件,则指定的不会上传到集群。要禁用.gitignore的考虑,请在进行上传的机器上设置RAY_RUNTIME_ENV_IGNORE_GITIGNORE=1。注意:如果本地目录包含符号链接,Ray 会跟踪链接,并且它们指向的文件将被上传到集群。
py_modules(List[str|module]):指定要在 Ray 工作进程中可供导入的 Python 模块。(有关指定包的更多方法,另请参阅下面的pip和conda字段。)每个条目必须是(1)一个本地文件或目录的路径,(2)一个远程 zip 或 wheel 文件的 URI(有关详细信息,请参阅 远程 URI),(3)一个 Python 模块对象,或(4)一个本地.whl文件的路径。列表中条目的示例:
".""/local_dependency/my_dir_module""/local_dependency/my_file_module.py""s3://bucket/my_module.zip"my_module # 假设 my_module 已 被 导入,例如 通过 'import my_module'my_module.whl"s3://bucket/my_module.whl"
模块将被下载到集群的每个节点上。
注意:目前不支持为每个任务或 actor 设置选项(1)、(3)和(4);它们只能为每个作业设置(即在
ray.init()中)。注意:对于选项(1),默认情况下,如果本地目录包含
.gitignore和/或.rayignore文件,则指定的不会上传到集群。要禁用.gitignore的考虑,请在进行上传的机器上设置RAY_RUNTIME_ENV_IGNORE_GITIGNORE=1。py_executable(str):指定用于运行 Ray 工作进程的可执行文件。它还可以包含参数。可执行文件可以位于working_dir中。此运行时环境可用于在自定义调试器或性能分析器中运行工作进程,以及在由UV等包管理器设置的环境中运行工作进程(请参阅 此处)。注意:
py_executable是新功能,目前处于实验阶段。如果您有任何需求或遇到任何问题,请在 GitHub 上提交 issue。excludes(List[str]):与working_dir或py_modules结合使用时,指定要排除上传到集群的文件或路径列表。此字段使用.gitignore文件使用的模式匹配语法:有关详细信息,请参阅 https://git-scm.cn/docs/gitignore。注意:根据.gitignore语法,如果模式的开头或中间(或两者)有分隔符(/),则该模式相对于working_dir的级别进行解释。特别是,您不应将绝对路径(例如/Users/my_working_dir/subdir/)与excludes一起使用;而是应使用相对路径/subdir/(此处写有前导/以仅匹配顶层subdir目录,而不是所有名为subdir的目录)。示例:
{"working_dir": "/Users/my_working_dir/", "excludes": ["my_file.txt", "/subdir/", "path/to/dir", "*.log"]}
pip(dict | List[str] | str): Either (1) a list of pip requirements specifiers, (2) a string containing the path to a local pip “requirements.txt” file, or (3) a python dictionary that has three fields: (a)packages(required, List[str]): a list of pip packages, (b)pip_check(optional, bool): whether to enable pip check at the end of pip install, defaults toFalse. (c)pip_version(optional, str): the version of pip; Ray will spell the package name “pip” in front of thepip_versionto form the final requirement string. (d)pip_install_options(optional, List[str]): user-provided options forpip installcommand. Defaults to["--disable-pip-version-check", "--no-cache-dir"]. The syntax of a requirement specifier is defined in full in PEP 508. This will be installed in the Ray workers at runtime. Packages in the preinstalled cluster environment will still be available. To use a library like Ray Serve or Ray Tune, you will need to include"ray[serve]"or"ray[tune]"here. The Ray version must match that of the cluster.示例:
["requests==1.0.0", "aiohttp", "ray[serve]"]示例:
"./requirements.txt"示例:
{"packages":["tensorflow", "requests"], "pip_check": False, "pip_version": "==22.0.2;python_version=='3.8.11'"}
当指定 requirements.txt 文件路径时,该文件必须存在于您的本地机器上,并且必须是一个有效的绝对路径或相对于您本地当前工作目录的相对文件路径,而不是相对于 runtime_env 中指定的 working_dir。此外,直接引用 requirements.txt 文件内的本地文件(例如,-r ./my-laptop/more-requirements.txt,./my-pkg.whl)不受支持。而是,请在创建过程中使用 ${RAY_RUNTIME_ENV_CREATE_WORKING_DIR} 环境变量。例如,使用 -r ${RAY_RUNTIME_ENV_CREATE_WORKING_DIR}/my-laptop/more-requirements.txt 或 ${RAY_RUNTIME_ENV_CREATE_WORKING_DIR}/my-pkg.whl 来引用本地文件,同时确保它们位于 working_dir 中。
uv(dict | List[str] | str): Alpha version feature. This plugin is theuv pipversion of thepipplugin above. If you are looking foruv runsupport withpyproject.tomlanduv.locksupport, use the uv run runtime environment plugin instead.Either (1) a list of uv requirements specifiers, (2) a string containing the path to a local uv “requirements.txt” file, or (3) a python dictionary that has three fields: (a)
packages(required, List[str]): a list of uv packages, (b)uv_version(optional, str): the version of uv; Ray will spell the package name “uv” in front of theuv_versionto form the final requirement string. (c)uv_check(optional, bool): whether to enable pip check at the end of uv install, default to False. (d)uv_pip_install_options(optional, List[str]): user-provided options foruv pip installcommand, default to["--no-cache"]. To override the default options and install without any options, use an empty list[]as install option value. The syntax of a requirement specifier is the same aspiprequirements. This will be installed in the Ray workers at runtime. Packages in the preinstalled cluster environment will still be available. To use a library like Ray Serve or Ray Tune, you will need to include"ray[serve]"or"ray[tune]"here. The Ray version must match that of the cluster.示例:
["requests==1.0.0", "aiohttp", "ray[serve]"]示例:
"./requirements.txt"示例:
{"packages":["tensorflow", "requests"], "uv_version": "==0.4.0;python_version=='3.8.11'"}
当指定 requirements.txt 文件路径时,该文件必须存在于您的本地机器上,并且必须是一个有效的绝对路径或相对于您本地当前工作目录的相对文件路径,而不是相对于 runtime_env 中指定的 working_dir。此外,直接引用 requirements.txt 文件内的本地文件(例如,-r ./my-laptop/more-requirements.txt,./my-pkg.whl)不受支持。而是,请在创建过程中使用 ${RAY_RUNTIME_ENV_CREATE_WORKING_DIR} 环境变量。例如,使用 -r ${RAY_RUNTIME_ENV_CREATE_WORKING_DIR}/my-laptop/more-requirements.txt 或 ${RAY_RUNTIME_ENV_CREATE_WORKING_DIR}/my-pkg.whl 来引用本地文件,同时确保它们位于 working_dir 中。
conda(dict | str): Either (1) a dict representing the conda environment YAML, (2) a string containing the path to a local conda “environment.yml” file, or (3) the name of a local conda environment already installed on each node in your cluster (e.g.,"pytorch_p36") or its absolute path (e.g."/home/youruser/anaconda3/envs/pytorch_p36") . In the first two cases, the Ray and Python dependencies will be automatically injected into the environment to ensure compatibility, so there is no need to manually include them. The Python and Ray version must match that of the cluster, so you likely should not specify them manually. Note that thecondaandpipkeys ofruntime_envcannot both be specified at the same time—to use them together, please usecondaand add your pip dependencies in the"pip"field in your condaenvironment.yaml.示例:
{"dependencies": ["pytorch", "torchvision", "pip", {"pip": ["pendulum"]}]}示例:
"./environment.yml"示例:
"pytorch_p36"示例:
"/home/youruser/anaconda3/envs/pytorch_p36"
When specifying a path to a
environment.ymlfile, the file must be present on your local machine and it must be a valid absolute path or a relative filepath relative to your local current working directory, not relative to theworking_dirspecified in theruntime_env. Furthermore, referencing local files within aenvironment.ymlfile isn’t directly supported (e.g.,-r ./my-laptop/more-requirements.txt,./my-pkg.whl). Instead, use the${RAY_RUNTIME_ENV_CREATE_WORKING_DIR}environment variable in the creation process. For example, use-r ${RAY_RUNTIME_ENV_CREATE_WORKING_DIR}/my-laptop/more-requirements.txtor${RAY_RUNTIME_ENV_CREATE_WORKING_DIR}/my-pkg.whlto reference local files, while ensuring they’re in theworking_dir.env_vars(Dict[str, str]): Environment variables to set. Environment variables already set on the cluster will still be visible to the Ray workers; so there is no need to includeos.environor similar in theenv_varsfield. By default, these environment variables override the same name environment variables on the cluster. You can also reference existing environment variables using ${ENV_VAR} to achieve the appending behavior. If the environment variable doesn’t exist, it becomes an empty string"".示例:
{"OMP_NUM_THREADS": "32", "TF_WARNINGS": "none"}示例:
{"LD_LIBRARY_PATH": "${LD_LIBRARY_PATH}:/home/admin/my_lib"}不存在的变量示例:
{"ENV_VAR_NOT_EXIST": "${ENV_VAR_NOT_EXIST}:/home/admin/my_lib"}->ENV_VAR_NOT_EXIST=":/home/admin/my_lib".
nsight(Union[str, Dict[str, str]]): specifies the config for the Nsight System Profiler. The value is either (1) “default”, which refers to the default config, or (2) a dict of Nsight System Profiler options and their values. See here for more details on setup and usage.示例:
"default"示例:
{"stop-on-exit": "true", "t": "cuda,cublas,cudnn", "ftrace": ""}
image_uri(dict): Require a given Docker image. The worker process runs in a container with this image. - Example:{"image_uri": "anyscale/ray:2.31.0-py39-cpu"}Note:
image_uriis experimental. If you have some requirements or run into any problems, raise issues in github.config(dict |ray.runtime_env.RuntimeEnvConfig): config for runtime environment. Either a dict or a RuntimeEnvConfig. Fields: (1) setup_timeout_seconds, the timeout of runtime environment creation, timeout is in seconds.示例:
{"setup_timeout_seconds": 10}示例:
RuntimeEnvConfig(setup_timeout_seconds=10)
(2)
eager_install(bool): Indicates whether to install the runtime environment on the cluster atray.init()time, before the workers are leased. This flag is set toTrueby default. If set toFalse, the runtime environment will be only installed when the first task is invoked or when the first actor is created. Currently, specifying this option per-actor or per-task is not supported.示例:
{"eager_install": False}示例:
RuntimeEnvConfig(eager_install=False)
Caching and Garbage Collection#
Runtime environment resources on each node (such as conda environments, pip packages, or downloaded working_dir or py_modules directories) will be cached on the cluster to enable quick reuse across different runtime environments within a job. Each field (working_dir, py_modules, etc.) has its own cache whose size defaults to 10 GB. To change this default, you may set the environment variable RAY_RUNTIME_ENV_<field>_CACHE_SIZE_GB on each node in your cluster before starting Ray e.g. export RAY_RUNTIME_ENV_WORKING_DIR_CACHE_SIZE_GB=1.5.
When the cache size limit is exceeded, resources not currently used by any Actor, Task or Job are deleted.
Runtime Environment Specified by Both Job and Driver#
When running an entrypoint script (Driver), the runtime environment can be specified via ray.init(runtime_env=...) or ray job submit --runtime-env (See Specifying a Runtime Environment Per-Job for more details).
If the runtime environment is specified by
ray job submit --runtime-env=..., the runtime environments are applied to the entrypoint script (Driver) and all the tasks and actors created from it.If the runtime environment is specified by
ray.init(runtime_env=...), the runtime environments are applied to all the tasks and actors, but not the entrypoint script (Driver) itself.
Since ray job submit submits a Driver (that calls ray.init), sometimes runtime environments are specified by both of them. When both the Ray Job and Driver specify runtime environments, their runtime environments are merged if there’s no conflict. It means the driver script uses the runtime environment specified by ray job submit, and all the tasks and actors are going to use the merged runtime environment. Ray raises an exception if the runtime environments conflict.
The
runtime_env["env_vars"]ofray job submit --runtime-env=...is merged with theruntime_env["env_vars"]ofray.init(runtime_env=...). Note that each individual env_var keys are merged. If the environment variables conflict, Ray raises an exception.Every other field in the
runtime_envwill be merged. If any key conflicts, it raises an exception.
示例
# `ray job submit --runtime_env=...`
{"pip": ["requests", "chess"],
"env_vars": {"A": "a", "B": "b"}}
# ray.init(runtime_env=...)
{"env_vars": {"C": "c"}}
# Driver's actual `runtime_env` (merged with Job's)
{"pip": ["requests", "chess"],
"env_vars": {"A": "a", "B": "b", "C": "c"}}
Conflict Example
# Example 1, env_vars conflicts
# `ray job submit --runtime_env=...`
{"pip": ["requests", "chess"],
"env_vars": {"C": "a", "B": "b"}}
# ray.init(runtime_env=...)
{"env_vars": {"C": "c"}}
# Ray raises an exception because the "C" env var conflicts.
# Example 2, other field (e.g., pip) conflicts
# `ray job submit --runtime_env=...`
{"pip": ["requests", "chess"]}
# ray.init(runtime_env=...)
{"pip": ["torch"]}
# Ray raises an exception because "pip" conflicts.
You can set an environment variable RAY_OVERRIDE_JOB_RUNTIME_ENV=1 to avoid raising an exception upon a conflict. In this case, the runtime environments are inherited in the same way as Driver and Task and Actor both specify runtime environments, where ray job submit is a parent and ray.init is a child.
Inheritance#
The runtime environment is inheritable, so it applies to all Tasks and Actors within a Job and all child Tasks and Actors of a Task or Actor once set, unless it is overridden.
If an Actor or Task specifies a new runtime_env, it overrides the parent’s runtime_env (i.e., the parent Actor’s or Task’s runtime_env, or the Job’s runtime_env if Actor or Task doesn’t have a parent) as follows
The
runtime_env["env_vars"]field will be merged with theruntime_env["env_vars"]field of the parent. This allows for environment variables set in the parent’s runtime environment to be automatically propagated to the child, even if new environment variables are set in the child’s runtime environment.Every other field in the
runtime_envwill be overridden by the child, not merged. For example, ifruntime_env["py_modules"]is specified, it will replace theruntime_env["py_modules"]field of the parent.
示例
# Parent's `runtime_env`
{"pip": ["requests", "chess"],
"env_vars": {"A": "a", "B": "b"}}
# Child's specified `runtime_env`
{"pip": ["torch", "ray[serve]"],
"env_vars": {"B": "new", "C": "c"}}
# Child's actual `runtime_env` (merged with parent's)
{"pip": ["torch", "ray[serve]"],
"env_vars": {"A": "a", "B": "new", "C": "c"}}
Frequently Asked Questions#
Are environments installed on every node?#
If a runtime environment is specified in ray.init(runtime_env=...), then the environment will be installed on every node. See Per-Job for more details. (Note, by default the runtime environment will be installed eagerly on every node in the cluster. If you want to lazily install the runtime environment on demand, set the eager_install option to false: ray.init(runtime_env={..., "config": {"eager_install": False}}.)
When is the environment installed?#
When specified per-job, the environment is installed when you call ray.init() (unless "eager_install": False is set). When specified per-task or per-actor, the environment is installed when the task is invoked or the actor is instantiated (i.e. when you call my_task.remote() or my_actor.remote().) See Per-Job Per-Task/Actor, within a job for more details.
Where are the environments cached?#
Any local files downloaded by the environments are cached at /tmp/ray/session_latest/runtime_resources.
How long does it take to install or to load from cache?#
The install time usually mostly consists of the time it takes to run pip install or conda create / conda activate, or to upload/download a working_dir, depending on which runtime_env options you’re using. This could take seconds or minutes.
On the other hand, loading a runtime environment from the cache should be nearly as fast as the ordinary Ray worker startup time, which is on the order of a few seconds. A new Ray worker is started for every Ray actor or task that requires a new runtime environment. (Note that loading a cached conda environment could still be slow, since the conda activate command sometimes takes a few seconds.)
You can set setup_timeout_seconds config to avoid the installation hanging for a long time. If the installation is not finished within this time, your tasks or actors will fail to start.
What is the relationship between runtime environments and Docker?#
They can be used independently or together. A container image can be specified in the Cluster Launcher for large or static dependencies, and runtime environments can be specified per-job or per-task/actor for more dynamic use cases. The runtime environment will inherit packages, files, and environment variables from the container image.
My runtime_env was installed, but when I log into the node I can’t import the packages.#
The runtime environment is only active for the Ray worker processes; it does not install any packages “globally” on the node.
Remote URIs#
The working_dir and py_modules arguments in the runtime_env dictionary can specify either local path(s) or remote URI(s).
A local path must be a directory path. The directory’s contents will be directly accessed as the working_dir or a py_module. A remote URI must be a link directly to a zip file or a wheel file (only for py_module). The zip file must contain only a single top-level directory. The contents of this directory will be directly accessed as the working_dir or a py_module.
For example, suppose you want to use the contents in your local /some_path/example_dir directory as your working_dir. If you want to specify this directory as a local path, your runtime_env dictionary should contain
runtime_env = {..., "working_dir": "/some_path/example_dir", ...}
Suppose instead you want to host your files in your /some_path/example_dir directory remotely and provide a remote URI. You would need to first compress the example_dir directory into a zip file.
There should be no other files or directories at the top level of the zip file, other than example_dir. You can use the following command in the Terminal to do this
cd /some_path
zip -r zip_file_name.zip example_dir
Note that this command must be run from the parent directory of the desired working_dir to ensure that the resulting zip file contains a single top-level directory. In general, the zip file’s name and the top-level directory’s name can be anything. The top-level directory’s contents will be used as the working_dir (or py_module).
You can check that the zip file contains a single top-level directory by running the following command in the Terminal
zipinfo -1 zip_file_name.zip
# example_dir/
# example_dir/my_file_1.txt
# example_dir/subdir/my_file_2.txt
Suppose you upload the compressed example_dir directory to AWS S3 at the S3 URI s3://example_bucket/example.zip. Your runtime_env dictionary should contain
runtime_env = {..., "working_dir": "s3://example_bucket/example.zip", ...}
警告
Check for hidden files and metadata directories in zipped dependencies. You can inspect a zip file’s contents by running the zipinfo -1 zip_file_name.zip command in the Terminal. Some zipping methods can cause hidden files or metadata directories to appear in the zip file at the top level. To avoid this, use the zip -r command directly on the directory you want to compress from its parent’s directory. For example, if you have a directory structure such as: a/b and you want to compress b, issue the zip -r b command from the directory a. If Ray detects more than a single directory at the top level, it will use the entire zip file instead of the top-level directory, which may lead to unexpected behavior.
Currently, four types of remote URIs are supported for hosting working_dir and py_modules packages
HTTPS:HTTPSrefers to URLs that start withhttps. These are particularly useful because remote Git providers (e.g. GitHub, Bitbucket, GitLab, etc.) usehttpsURLs as download links for repository archives. This allows you to host your dependencies on remote Git providers, push updates to them, and specify which dependency versions (i.e. commits) your jobs should use. To use packages viaHTTPSURIs, you must have thesmart_openlibrary (you can install it usingpip install smart_open).示例
runtime_env = {"working_dir": "https://github.com/example_username/example_repository/archive/HEAD.zip"}
S3:S3refers to URIs starting withs3://that point to compressed packages stored in AWS S3. To use packages viaS3URIs, you must have thesmart_openandboto3libraries (you can install them usingpip install smart_openandpip install boto3). Ray does not explicitly pass in any credentials toboto3for authentication.boto3will use your environment variables, shared credentials file, and/or AWS config file to authenticate access. See the AWS boto3 documentation to learn how to configure these.示例
runtime_env = {"working_dir": "s3://example_bucket/example_file.zip"}
GS:GSrefers to URIs starting withgs://that point to compressed packages stored in Google Cloud Storage. To use packages viaGSURIs, you must have thesmart_openandgoogle-cloud-storagelibraries (you can install them usingpip install smart_openandpip install google-cloud-storage). Ray does not explicitly pass in any credentials to thegoogle-cloud-storage’sClientobject.google-cloud-storagewill use your local service account key(s) and environment variables by default. Follow the steps on Google Cloud Storage’s Getting started with authentication guide to set up your credentials, which allow Ray to access your remote package.示例
runtime_env = {"working_dir": "gs://example_bucket/example_file.zip"}
Azure:Azure指的是以azure://开头的 URI,指向存储在 Azure Blob Storage 中的压缩包。要通过AzureURI 使用包,您必须安装smart_open、azure-storage-blob和azure-identity库(可以使用pip install smart_open[azure] azure-storage-blob azure-identity命令安装)。Ray 支持两种 Azure Blob Storage 的身份验证方法。连接字符串:将环境变量
AZURE_STORAGE_CONNECTION_STRING设置为您的 Azure 存储连接字符串。托管标识:将环境变量
AZURE_STORAGE_ACCOUNT设置为您的 Azure 存储账户名。这将使用 Azure 的托管标识进行身份验证。
示例
runtime_env = {"working_dir": "azure://container-name/example_file.zip"}
请注意,smart_open、boto3、google-cloud-storage、azure-storage-blob 和 azure-identity 包默认未安装,并且仅在 runtime_env 的 pip 部分指定是不够的。在 Ray 启动时,相关的包必须已安装在集群的所有节点上。
在远程 Git 提供商上托管依赖项:分步指南#
您可以将依赖项存储在远程 Git 提供商(例如 GitHub、Bitbucket、GitLab 等)的仓库中,并定期推送更改以保持更新。在本节中,您将学习如何在 GitHub 上存储依赖项并在您的运行时环境中对其进行使用。
注意
如果您使用其他大型远程 Git 提供商(例如 BitBucket、GitLab 等),这些步骤也将非常有用。为简单起见,本节仅提及 GitHub,但您可以根据您使用的提供商进行操作。
首先,在 GitHub 上创建一个仓库来存储您的 working_dir 内容或您的 py_module 依赖项。默认情况下,当您下载仓库的 zip 文件时,该 zip 文件将包含一个包含仓库内容的顶级目录,因此您可以直接将 working_dir 内容或 py_module 依赖项上传到 GitHub 仓库。
上传完 working_dir 内容或 py_module 依赖项后,您需要仓库 zip 文件的 HTTPS URL,以便在 runtime_env 字典中指定它。
您有两个选项可以获取 HTTPS URL。
选项 1:下载 Zip(实现更快,但不推荐用于生产环境)#
第一个选项是使用远程 Git 提供商的“下载 Zip”功能,该功能提供一个 HTTPS 链接来压缩并下载您的仓库。这很快,但**不推荐**,因为它只允许您下载仓库分支最新提交的 zip 文件。要查找 GitHub URL,请导航到您在 GitHub 上的仓库,选择一个分支,然后单击绿色的“Code”下拉按钮。
这将弹出一个菜单,提供三个选项:“Clone”(提供克隆仓库的 HTTPS/SSH 链接)、“Open with GitHub Desktop”和“Download ZIP”。右键单击“Download Zip”。这会在光标附近打开一个弹出窗口。选择“Copy Link Address”。
现在您的 HTTPS 链接已复制到剪贴板。您可以将其粘贴到您的 runtime_env 字典中。
警告
如果 URL 始终指向最新提交,则不建议使用来自 Git 提供商的“下载为 Zip”功能的 HTTPS URL。例如,在 GitHub 上使用此方法生成的链接始终指向所选分支的最新提交。
通过在 runtime_env 字典中指定此链接,您的 Ray 集群将始终使用所选分支的最新提交。这会带来一致性风险:如果您在集群节点正在拉取仓库内容时向远程 Git 仓库推送更新,一些节点可能会拉取您推送之前的版本,而另一些节点可能会拉取您推送之后的新版本。为了保持一致性,最好指定一个特定的提交,以便所有节点都使用相同的包。有关如何创建指向特定提交的 URL,请参阅“选项 2:手动创建 URL”。
选项 2:手动创建 URL(实现较慢,但推荐用于生产环境)#
第二个选项是通过模式匹配您的具体用例并使用以下示例之一来手动创建此 URL。**此方法推荐使用**,因为它在生成依赖项 zip 文件时提供了对要使用的仓库分支和提交的更精细控制。这些选项可以防止 Ray 集群出现一致性问题(有关更多信息,请参阅上面的警告)。要创建 URL,请从下面的 URL 模板中选择一个适合您用例的模板,并用您仓库中的具体值填充所有方括号中的参数(例如 [username]、[repository] 等)。例如,假设您的 GitHub 用户名为 example_user,仓库名称为 example_repository,并且所需的提交哈希为 abcdefg。如果 example_repository 是公共仓库,并且您想要检索 abcdefg 提交(对应第一个示例用例),则 URL 将为:
runtime_env = {"working_dir": ("https://github.com"
"/example_user/example_repository/archive/abcdefg.zip")}
以下是不同用例和相应 URL 的列表
示例:从公共 GitHub 仓库的特定提交哈希检索包
runtime_env = {"working_dir": ("https://github.com"
"/[username]/[repository]/archive/[commit hash].zip")}
示例:使用个人访问令牌从私有 GitHub 仓库检索包**在开发期间**。**生产环境**请参阅本文档,了解如何安全地进行私有依赖项的身份验证。
runtime_env = {"working_dir": ("https://[username]:[personal access token]@github.com"
"/[username]/[private repository]/archive/[commit hash].zip")}
示例:从公共 GitHub 仓库的最新提交检索包
runtime_env = {"working_dir": ("https://github.com"
"/[username]/[repository]/archive/HEAD.zip")}
示例:从公共 Bitbucket 仓库的特定提交哈希检索包
runtime_env = {"working_dir": ("https://bitbucket.org"
"/[owner]/[repository]/get/[commit hash].tar.gz")}
提示
建议指定特定提交而不是始终使用最新提交。这可以防止在多节点 Ray 集群中出现一致性问题。有关更多信息,请参阅“选项 1:下载 Zip”下方的警告。
在 runtime_env 字典中指定 URL 后,您可以将该字典传递给 ray.init() 或 .options() 调用。恭喜!您已成功在 GitHub 上远程托管了一个 runtime_env 依赖项!
调试#
如果无法设置 runtime_env(例如,网络问题、下载失败等),Ray 将无法调度需要 runtime_env 的任务/Actor。如果您调用 ray.get,它将引发 RuntimeEnvSetupError 并附带详细的错误消息。
import ray
import time
@ray.remote
def f():
pass
@ray.remote
class A:
def f(self):
pass
start = time.time()
bad_env = {"conda": {"dependencies": ["this_doesnt_exist"]}}
# [Tasks] will raise `RuntimeEnvSetupError`.
try:
ray.get(f.options(runtime_env=bad_env).remote())
except ray.exceptions.RuntimeEnvSetupError:
print("Task fails with RuntimeEnvSetupError")
# [Actors] will raise `RuntimeEnvSetupError`.
a = A.options(runtime_env=bad_env).remote()
try:
ray.get(a.f.remote())
except ray.exceptions.RuntimeEnvSetupError:
print("Actor fails with RuntimeEnvSetupError")
Task fails with RuntimeEnvSetupError
Actor fails with RuntimeEnvSetupError
完整日志始终可以在 runtime_env_setup-[job_id].log 文件中找到,用于每个 Actor、每个任务和每个作业的环境,或者在使用 Ray Client 进行每个作业的环境时,可以在 runtime_env_setup-ray_client_server_[port].log 中找到。
您还可以通过在每个节点上启动 Ray 之前设置环境变量 RAY_RUNTIME_ENV_LOG_TO_DRIVER_ENABLED=1 来启用 runtime_env 调试日志流式传输,例如使用 Ray 集群配置文件中的 setup_commands(请参阅 参考)。这将把完整的 runtime_env 设置日志消息打印到驱动程序(调用 ray.init() 的脚本)。
示例日志输出
ray.init(runtime_env={"pip": ["requests"]})
(pid=runtime_env) 2022-02-28 14:12:33,653 INFO pip.py:188 -- Creating virtualenv at /tmp/ray/session_2022-02-28_14-12-29_909064_87908/runtime_resources/pip/0cc818a054853c3841171109300436cad4dcf594/virtualenv, current python dir /Users/user/anaconda3/envs/ray-py38
(pid=runtime_env) 2022-02-28 14:12:33,653 INFO utils.py:76 -- Run cmd[1] ['/Users/user/anaconda3/envs/ray-py38/bin/python', '-m', 'virtualenv', '--app-data', '/tmp/ray/session_2022-02-28_14-12-29_909064_87908/runtime_resources/pip/0cc818a054853c3841171109300436cad4dcf594/virtualenv_app_data', '--reset-app-data', '--no-periodic-update', '--system-site-packages', '--no-download', '/tmp/ray/session_2022-02-28_14-12-29_909064_87908/runtime_resources/pip/0cc818a054853c3841171109300436cad4dcf594/virtualenv']
(pid=runtime_env) 2022-02-28 14:12:34,267 INFO utils.py:97 -- Output of cmd[1]: created virtual environment CPython3.8.11.final.0-64 in 473ms
(pid=runtime_env) creator CPython3Posix(dest=/private/tmp/ray/session_2022-02-28_14-12-29_909064_87908/runtime_resources/pip/0cc818a054853c3841171109300436cad4dcf594/virtualenv, clear=False, no_vcs_ignore=False, global=True)
(pid=runtime_env) seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/private/tmp/ray/session_2022-02-28_14-12-29_909064_87908/runtime_resources/pip/0cc818a054853c3841171109300436cad4dcf594/virtualenv_app_data)
(pid=runtime_env) added seed packages: pip==22.0.3, setuptools==60.6.0, wheel==0.37.1
(pid=runtime_env) activators BashActivator,CShellActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator
(pid=runtime_env)
(pid=runtime_env) 2022-02-28 14:12:34,268 INFO utils.py:76 -- Run cmd[2] ['/tmp/ray/session_2022-02-28_14-12-29_909064_87908/runtime_resources/pip/0cc818a054853c3841171109300436cad4dcf594/virtualenv/bin/python', '-c', 'import ray; print(ray.__version__, ray.__path__[0])']
(pid=runtime_env) 2022-02-28 14:12:35,118 INFO utils.py:97 -- Output of cmd[2]: 3.0.0.dev0 /Users/user/ray/python/ray
(pid=runtime_env)
(pid=runtime_env) 2022-02-28 14:12:35,120 INFO pip.py:236 -- Installing python requirements to /tmp/ray/session_2022-02-28_14-12-29_909064_87908/runtime_resources/pip/0cc818a054853c3841171109300436cad4dcf594/virtualenv
(pid=runtime_env) 2022-02-28 14:12:35,122 INFO utils.py:76 -- Run cmd[3] ['/tmp/ray/session_2022-02-28_14-12-29_909064_87908/runtime_resources/pip/0cc818a054853c3841171109300436cad4dcf594/virtualenv/bin/python', '-m', 'pip', 'install', '--disable-pip-version-check', '--no-cache-dir', '-r', '/tmp/ray/session_2022-02-28_14-12-29_909064_87908/runtime_resources/pip/0cc818a054853c3841171109300436cad4dcf594/requirements.txt']
(pid=runtime_env) 2022-02-28 14:12:38,000 INFO utils.py:97 -- Output of cmd[3]: Requirement already satisfied: requests in /Users/user/anaconda3/envs/ray-py38/lib/python3.8/site-packages (from -r /tmp/ray/session_2022-02-28_14-12-29_909064_87908/runtime_resources/pip/0cc818a054853c3841171109300436cad4dcf594/requirements.txt (line 1)) (2.26.0)
(pid=runtime_env) Requirement already satisfied: idna<4,>=2.5 in /Users/user/anaconda3/envs/ray-py38/lib/python3.8/site-packages (from requests->-r /tmp/ray/session_2022-02-28_14-12-29_909064_87908/runtime_resources/pip/0cc818a054853c3841171109300436cad4dcf594/requirements.txt (line 1)) (3.2)
(pid=runtime_env) Requirement already satisfied: certifi>=2017.4.17 in /Users/user/anaconda3/envs/ray-py38/lib/python3.8/site-packages (from requests->-r /tmp/ray/session_2022-02-28_14-12-29_909064_87908/runtime_resources/pip/0cc818a054853c3841171109300436cad4dcf594/requirements.txt (line 1)) (2021.10.8)
(pid=runtime_env) Requirement already satisfied: urllib3<1.27,>=1.21.1 in /Users/user/anaconda3/envs/ray-py38/lib/python3.8/site-packages (from requests->-r /tmp/ray/session_2022-02-28_14-12-29_909064_87908/runtime_resources/pip/0cc818a054853c3841171109300436cad4dcf594/requirements.txt (line 1)) (1.26.7)
(pid=runtime_env) Requirement already satisfied: charset-normalizer~=2.0.0 in /Users/user/anaconda3/envs/ray-py38/lib/python3.8/site-packages (from requests->-r /tmp/ray/session_2022-02-28_14-12-29_909064_87908/runtime_resources/pip/0cc818a054853c3841171109300436cad4dcf594/requirements.txt (line 1)) (2.0.6)
(pid=runtime_env)
(pid=runtime_env) 2022-02-28 14:12:38,001 INFO utils.py:76 -- Run cmd[4] ['/tmp/ray/session_2022-02-28_14-12-29_909064_87908/runtime_resources/pip/0cc818a054853c3841171109300436cad4dcf594/virtualenv/bin/python', '-c', 'import ray; print(ray.__version__, ray.__path__[0])']
(pid=runtime_env) 2022-02-28 14:12:38,804 INFO utils.py:97 -- Output of cmd[4]: 3.0.0.dev0 /Users/user/ray/python/ray
有关更多详细信息,请参阅 日志目录结构。