# PR #7313 完整报告

- 仓库：`verl-project/verl`
- 标题：[ray] fix: remove conflicting PYTHONPATH forwarding
- 合并时间：2026-08-10 14:03
- 原文链接：http://prhub.com.cn/verl-project/verl/pull/7313

---

# 执行摘要

- 一句话：移除 Ray runtime env 中 PYTHONPATH 转发，修复作业提交冲突
- 推荐动作：值得快速浏览，不必精读。核心收获是 Ray runtime_env 合并的约束：同名键会在 Job-level 与 programmatic 之间冲突。如果团队经常使用 Ray Job 提交训练，建议在文档中明确 PYTHONPATH 必须通过 runtime-env 提供；若存在 out-of-band ray start 场景，可在未来通过更明确的配置开关替代自动转发。

# 功能与动机

PR body 明确指出：When a job submitted through ray job submit --runtime-env already defines PYTHONPATH, verl adds the same key again to ray.init(runtime_env=...). Ray rejects the merge and training fails before initialization. 因此需要撤销 #7101 引入的自动转发，避免重复键冲突导致训练无法启动。

# 实现拆解

1. 定位变更入口：`verl/trainer/constants_ppo.py` 中的 `get_ppo_ray_runtime_env(config=None)` 是构造 PPO Ray 运行时环境的核心函数，它在调用时复制 `PPO_RAY_RUNTIME_ENV["env_vars"]`，过滤已存在的变量，并强制注入确定性相关变量。
2. 删除 PYTHONPATH 转发：base 版本在函数末尾检测 `os.environ.get("PYTHONPATH")`，若非空则写入 `runtime_env["env_vars"]["PYTHONPATH"]`；head 版本删除这段逻辑（含 3 行注释），函数在注入四个确定性变量后直接返回 runtime_env。
3. 保留既有行为：过滤逻辑、Megatron/MindSpeed 的 `CUDA_DEVICE_MAX_CONNECTIONS` 设置、以及 `PYTHONHASHSEED` 等变量的注入均保持不变，未影响其他调用方。
4. 测试与配套：本次没有新增或修改测试，也没有配置文件或部署脚本变更；PR 仅通过 pre-commit 对 `constants_ppo.py` 的检查。潜在回归风险在于依赖自动转发的非 Ray Job 场景。

关键文件：
- `verl/trainer/constants_ppo.py`（模块 训练入口；类别 source；类型 core-logic；符号 get_ppo_ray_runtime_env）: 唯一变更文件，get_ppo_ray_runtime_env() 是 PPO Ray runtime env 的唯一构造入口，删除 PYTHONPATH 转发直接影响所有 Ray 后端 PPO 训练的启动行为。

关键符号：get_ppo_ray_runtime_env

## 关键源码片段

### `verl/trainer/constants_ppo.py`

唯一变更文件，get_ppo_ray_runtime_env() 是 PPO Ray runtime env 的唯一构造入口，删除 PYTHONPATH 转发直接影响所有 Ray 后端 PPO 训练的启动行为。

```python
def get_ppo_ray_runtime_env(config=None):
    """
    返回 PPO 训练使用的 Ray runtime environment。

    该函数避免重复注入当前进程已经存在的环境变量，
    并始终在调用时刻（而非 import 时刻）注入关键变量。

    Args:
        config: 可选训练配置。当引擎策略为 Megatron 且 GPU 是 Hopper/Ampere 时，
            会额外设置 CUDA_DEVICE_MAX_CONNECTIONS=1。
    """
    # 从 Ray Job 配置中读取 working_dir，避免重复设置
    working_dir = (
        json.loads(os.environ.get(RAY_JOB_CONFIG_JSON_ENV_VAR, "{}"))
        .get("runtime_env", {})
        .get("working_dir", None)
    )

    runtime_env = {
        "env_vars": PPO_RAY_RUNTIME_ENV["env_vars"].copy(),
        **({"working_dir": None} if working_dir is None else {}),
    }

    # 仅 Megatron 在 Hopper/Ampere 上需要该设置，MindSpeed 也需要
    if _is_hopper_or_ampere and _uses_megatron(config):
        runtime_env["env_vars"]["CUDA_DEVICE_MAX_CONNECTIONS"] = "1"
    if _uses_mindspeed(config):
        runtime_env["env_vars"]["CUDA_DEVICE_MAX_CONNECTIONS"] = "1"

    # 当前进程已设置过的变量不再重复注入，避免覆盖已有值
    for key in list(runtime_env["env_vars"].keys()):
        if os.environ.get(key) is not None:
            runtime_env["env_vars"].pop(key, None)

    # 这四个变量始终在调用时注入（而不是 import 时）
    for key in ("PYTHONHASHSEED", "VERL_FULL_DETERMINISM", "VLLM_BATCH_INVARIANT", "VERL_RL_INSIGHT_ENABLE"):
        runtime_env["env_vars"][key] = os.environ.get(key, "0")

    # 注意：PR #7313 之前这里会把 driver 的 PYTHONPATH 转发给 Ray worker，
    # 但如果任务由 `ray job submit --runtime-env` 提交且已定义 PYTHONPATH，
    # 重复注入同一键会让 Ray 拒绝合并 runtime_env，训练在初始化前失败。
    # 因此该转发已被移除，PYTHONPATH 由 Ray Job runtime env 统一负责传播。
    return runtime_env

```

# 评论区精华

本 PR 没有任何 review 评论（comments_count=0、review_comments_count=0），由作者 yyDing1 直接提交、wuxibin89 合并。虽然没有公开讨论，核心设计权衡在于：修复了 Ray Job 合并冲突，但收紧了使用约定——自定义 PYTHONPATH 必须由 Ray Job runtime-env 显式提供；当初 #7101 为了支持 out-of-band ray start 场景而引入的自动转发被完全撤销。

- 暂无高价值评论线程

# 风险与影响

- 风险：兼容性风险：直接 `ray.init()` 或 `ray start` 集群上，driver 的 PYTHONPATH 不再自动传给 worker，依赖 PYTHONPATH 暴露的非 site-packages 包（如 CI 镜像中的 /workspace/Megatron-LM）可能 ImportError。缺少测试覆盖：无对应单元测试，后续若重新加入转发或调整 runtime_env 结构，无法自动发现冲突。正确性风险：修复依赖用户已在 Ray Job runtime-env 中正确设置 PYTHONPATH，否则行为会从原来的启动崩溃变为静默导入失败。
- 影响：用户侧：通过 `ray job submit --runtime-env` 提交且已定义 PYTHONPATH 的用户从启动崩溃变为正常训练；但未正确配置 runtime-env 的用户可能遇到新的导入失败。系统侧：`get_ppo_ray_runtime_env` 是所有 PPO Ray 训练的公用函数，影响所有 Ray 后端 PPO 配置的启动环节，但对默认（无 PYTHONPATH 需求）训练无影响。团队侧：撤销了 #7101 的兼容性设计，后续涉及 PYTHONPATH 传播的需求需在设计层面统一。
- 风险标记：Ray 启动路径变更 , 缺少测试覆盖 , 依赖外部 runtime_env 传递 PYTHONPATH

# 关联脉络

- PR #7101 PYTHONPATH forwarding (reverted by #7313): PR body 明确说明本 PR reverts #7101 引入的 PYTHONPATH 转发，二者构成直接 revert 关系。