1. 引言

2026 年,OpenAI 的 ChatGPT Plus 与 Pro 订阅方案,配合 Codex 编程助手,已经成为开发者日常工作中不可或缺的工具组合。很多朋友升级到 Plus 或 Pro 之后,只知道用网页版聊天,却不知道如何把 Codex 的能力真正接入自己的开发流程。

这篇文章不聊充值、不聊账号,只聊技术。我会从模型能力差异讲起,带你完成 Codex 的本地环境配置,然后通过几个真实可运行的代码示例,演示如何用 Codex 完成代码生成、仓库级重构、自动化测试编写,以及如何把它接入 CI/CD 流水线。全文 3000 字以上,所有代码均可直接复制运行。

2. 订阅方案与模型能力差异

在开始写代码之前,先搞清楚你手里的订阅到底给了你什么。ChatGPT Plus 与 Pro 在模型访问权限、上下文长度和速率限制上存在明显差异。

2.1 ChatGPT Plus

Plus 订阅主要面向日常使用,包含以下能力:

  • 访问 GPT-5 系列标准模型;
  • 中等优先级的推理算力;
  • 支持 Codex 云端沙箱的有限使用;
  • 标准速率限制。

对于偶尔写脚本、做代码审查的开发者,Plus 基本够用。

2.2 ChatGPT Pro

Pro 订阅面向重度用户,核心差异在于:

  • 无限制访问 GPT-5 高算力模式;
  • 更高频次的 Codex 任务并发;
  • 更长的上下文窗口支持;
  • 优先使用最新实验性模型。

如果你每天要处理大量代码任务,Pro 的体验会明显更流畅。

2.3 Codex 是什么

Codex 是 OpenAI 推出的编程智能体,它不只是补全代码,而是能理解整个仓库结构、执行命令、读取文件、运行测试并迭代修复。它运行在云端沙箱或本地环境中,通过自然语言指令完成复杂的工程任务。

下面用一个表格总结三者的定位差异:

项目ChatGPT PlusChatGPT ProCodex
定位日常问答重度推理编程智能体
上下文长度标准更长仓库级
代码执行受限更宽松完整沙箱
适用场景轻量开发复杂推理工程化开发

3. 环境准备与 Codex 接入

无论你用的是 Plus 还是 Pro,Codex 的接入方式基本一致。下面以本地 CLI 方式为例,演示完整配置流程。

3.1 安装 Codex CLI

Codex CLI 支持 macOS 与 Linux。打开终端执行:

npm install -g @openai/codex

安装完成后验证版本:

codex --version

如果输出类似 codex 0.4x.x 的版本号,说明安装成功。

3.2 登录认证

Codex CLI 需要登录你的 OpenAI 账号。执行:

codex login

浏览器会自动打开授权页面,登录后回到终端,会看到登录成功的提示。Codex 会自动读取你当前订阅对应的模型权限。

3.3 验证连通性

写一个最简单的测试任务,确认 Codex 能正常工作:

codex exec "用 Python 写一个快速排序函数,并附带单元测试"

Codex 会在沙箱中生成代码并运行测试。如果一切正常,你会看到类似下面的输出:

✓ 已生成 quick_sort.py
✓ 测试通过 (4 passed)

4. 用 Codex 生成高质量代码

这一节我们通过实际案例,演示如何用 Codex 完成一个完整的 Python 工具模块开发。

4.1 任务描述

假设我们需要一个「文件批量重命名工具」,要求如下:

  • 支持按规则批量重命名目录下的文件;
  • 支持前缀、后缀、序号填充三种模式;
  • 提供命令行入口;
  • 包含完整单元测试。

4.2 使用 Codex 生成

在项目目录下执行:

codex exec "在当前目录创建一个 Python 命令行工具,实现文件批量重命名:支持前缀、后缀、序号填充三种模式,使用 argparse 解析参数,并编写 pytest 单元测试"

Codex 会自动创建项目文件。生成的 renamer.py 核心代码如下:

import argparse
from pathlib import Path


def batch_rename(directory: str, prefix: str = "", suffix: str = "", pad: int = 0) -> int:
    """批量重命名目录下的文件。

    Args:
        directory: 目标目录路径。
        prefix: 文件名前缀。
        suffix: 文件名后缀(不含扩展名)。
        pad: 序号填充位数,0 表示不填充。

    Returns:
        重命名的文件数量。
    """
    target_dir = Path(directory)
    if not target_dir.is_dir():
        raise NotADirectoryError(f"{directory} 不是有效目录")

    renamed = 0
    for index, file_path in enumerate(target_dir.iterdir(), start=1):
        if not file_path.is_file():
            continue

        seq = str(index).zfill(pad) if pad > 0 else str(index)
        new_name = f"{prefix}{seq}{suffix}{file_path.suffix}"
        new_path = file_path.with_name(new_name)

        if new_path.exists():
            print(f"跳过 {file_path.name}:目标文件已存在")
            continue

        file_path.rename(new_path)
        renamed += 1
        print(f"{file_path.name} -> {new_name}")

    return renamed


def main() -> None:
    parser = argparse.ArgumentParser(description="批量文件重命名工具")
    parser.add_argument("directory", help="目标目录路径")
    parser.add_argument("--prefix", default="", help="文件名前缀")
    parser.add_argument("--suffix", default="", help="文件名后缀")
    parser.add_argument("--pad", type=int, default=0, help="序号填充位数")
    args = parser.parse_args()

    count = batch_rename(args.directory, args.prefix, args.suffix, args.pad)
    print(f"共重命名 {count} 个文件")


if __name__ == "__main__":
    main()

4.3 运行与测试

Codex 同时生成了测试文件 test_renamer.py

import pytest
from renamer import batch_rename


def test_batch_rename_with_prefix(tmp_path):
    for name in ["a.txt", "b.txt", "c.txt"]:
        (tmp_path / name).write_text("test")

    count = batch_rename(str(tmp_path), prefix="file_")

    assert count == 3
    files = sorted(p.name for p in tmp_path.iterdir())
    assert files == ["file_1.txt", "file_2.txt", "file_3.txt"]


def test_batch_rename_with_padding(tmp_path):
    for name in ["a.txt", "b.txt"]:
        (tmp_path / name).write_text("test")

    count = batch_rename(str(tmp_path), prefix="img_", pad=3)

    assert count == 2
    files = sorted(p.name for p in tmp_path.iterdir())
    assert files == ["img_001.txt", "img_002.txt"]


def test_batch_rename_invalid_directory():
    with pytest.raises(NotADirectoryError):
        batch_rename("/nonexistent/path")

运行测试:

pytest test_renamer.py -v

预期输出:

test_batch_rename_with_prefix ... PASSED
test_batch_rename_with_padding ... PASSED
test_batch_rename_invalid_directory ... PASSED

5. 用 Codex 做仓库级重构

Codex 的强项在于理解整个仓库结构。下面演示如何让它完成一次跨文件的代码重构。

5.1 场景描述

假设你的项目里有一个旧模块 legacy_utils.py,其中大量使用了 datetime.now() 直接获取时间,且函数命名不规范。你希望:

  • 统一时间获取方式,改为可注入的时钟;
  • 重命名不规范的函数;
  • 同步更新所有调用方。

5.2 发起重构指令

在项目根目录执行:

codex exec "重构 legacy_utils.py:将直接调用 datetime.now() 的地方改为可注入的 clock 参数,默认使用系统时间;将 get_timestamp_str 重命名为 get_timestamp;将 format_log_line 重命名为 format_log;同步更新仓库内所有调用这些函数的地方"

Codex 会扫描整个仓库,找出所有引用点并逐一修改。重构后的核心代码:

from datetime import datetime
from typing import Callable


def get_timestamp(clock: Callable[[], datetime] | None = None) -> str:
    """返回当前时间的格式化字符串。

    Args:
        clock: 可注入的时间函数,默认使用 datetime.now。

    Returns:
        形如 2026-09-02 15:20:21 的时间字符串。
    """
    now = clock() if clock else datetime.now()
    return now.strftime("%Y-%m-%d %H:%M:%S")


def format_log(message: str, level: str = "INFO", clock: Callable[[], datetime] | None = None) -> str:
    """格式化日志行。

    Args:
        message: 日志消息。
        level: 日志级别。
        clock: 可注入的时间函数。

    Returns:
        格式化后的日志行。
    """
    timestamp = get_timestamp(clock)
    return f"[{timestamp}] [{level}] {message}"

5.3 验证重构结果

Codex 会自动运行测试来验证重构没有破坏功能。你也可以手动检查所有调用点是否已更新:

grep -rn "get_timestamp_str\|format_log_line" --include="*.py" .

如果没有任何输出,说明旧函数名已全部替换干净。

6. 用 Codex 编写自动化测试

Codex 不仅能写业务代码,还能为已有代码自动生成高质量的测试。

6.1 准备被测代码

假设我们有如下一个订单折扣计算模块 discount.py

from dataclasses import dataclass


@dataclass
class Order:
    amount: float
    is_vip: bool = False
    coupon: float = 0.0


def calculate_discount(order: Order) -> float:
    """计算订单最终折扣金额。

    规则:
    1. VIP 用户享受 8 折;
    2. 普通用户满 100 减 20;
    3. 优惠券可与上述折扣叠加,但不能超过订单金额。
    """
    if order.is_vip:
        discount = order.amount * 0.2
    elif order.amount >= 100:
        discount = 20.0
    else:
        discount = 0.0

    total_discount = discount + order.coupon
    return min(total_discount, order.amount)

6.2 让 Codex 生成测试

执行:

codex exec "为 discount.py 编写 pytest 单元测试,覆盖 VIP、满减、优惠券叠加、折扣封顶等边界情况"

Codex 生成的测试文件:

import pytest
from discount import Order, calculate_discount


def test_vip_user_gets_20_percent_off():
    order = Order(amount=200.0, is_vip=True)
    assert calculate_discount(order) == 40.0


def test_regular_user_over_100_gets_20_off():
    order = Order(amount=150.0)
    assert calculate_discount(order) == 20.0


def test_regular_user_under_100_no_discount():
    order = Order(amount=80.0)
    assert calculate_discount(order) == 0.0


def test_coupon_stacks_with_vip_discount():
    order = Order(amount=200.0, is_vip=True, coupon=30.0)
    assert calculate_discount(order) == 70.0


def test_discount_cannot_exceed_order_amount():
    order = Order(amount=50.0, coupon=100.0)
    assert calculate_discount(order) == 50.0


def test_vip_discount_with_coupon_capped():
    order = Order(amount=100.0, is_vip=True, coupon=100.0)
    assert calculate_discount(order) == 100.0

6.3 运行测试并查看覆盖率

pytest test_discount.py -v --cov=discount --cov-report=term-missing

预期输出:

test_vip_user_gets_20_percent_off ... PASSED
test_regular_user_over_100_gets_20_off ... PASSED
test_regular_user_under_100_no_discount ... PASSED
test_coupon_stacks_with_vip_discount ... PASSED
test_discount_cannot_exceed_order_amount ... PASSED
test_vip_discount_with_coupon_capped ... PASSED

Name          Stmts   Miss  Cover   Missing
-------------------------------------------
discount.py       8      0   100%

7. 将 Codex 接入 CI/CD 流水线

Codex 的能力可以通过命令行集成到 GitHub Actions 中,实现「PR 自动代码审查」和「Issue 自动修复」。

7.1 配置 GitHub Actions

在仓库中创建 .github/workflows/codex-review.yml

name: Codex PR Review

on:
  pull_request:
    types: [opened, synchronize]

jobs:
  codex-review:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "20"

      - name: Install Codex CLI
        run: npm install -g @openai/codex

      - name: Run Codex Review
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: |
          codex exec "审查当前 PR 的代码变更,重点关注:1) 潜在的 bug;2) 安全问题;3) 性能瓶颈。输出审查意见。" \
            --review \
            --git-diff origin/main...HEAD

7.2 自动修复 Issue

你还可以创建一个「Issue 自动修复」工作流,当 Issue 被标记为 bug 时,让 Codex 自动尝试修复:

name: Codex Auto Fix

on:
  issues:
    types: [labeled]

jobs:
  auto-fix:
    if: github.event.label.name == 'bug'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "20"

      - name: Install Codex CLI
        run: npm install -g @openai/codex

      - name: Codex Attempt Fix
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: |
          codex exec "请修复 Issue #${{ github.event.issue.number }} 中描述的问题,创建修复分支并提交 PR" \
            --auto-fix \
            --issue-number ${{ github.event.issue.number }}

7.3 工作流示意

下面是 Codex 接入 CI 后的完整工作流:

开发者提交 PR

GitHub Actions 触发

安装 Codex CLI

Codex 读取变更 diff

是否存在问题?

生成审查意见并评论

输出通过提示

开发者根据意见修改

合并 PR

8. 常见问题与排查技巧

8.1 Codex 无法登录

如果执行 codex login 后浏览器没有弹出,可以尝试:

codex logout
codex login --headless

--headless 模式会在终端直接输出一个授权链接,手动复制到浏览器打开即可。

8.2 任务执行超时

对于大型重构任务,可以增加超时时间:

codex exec "重构任务描述" --timeout 600

单位是秒,上面的命令将超时时间设置为 10 分钟。

8.3 只想让 Codex 读代码不执行

某些场景下你只希望 Codex 分析代码而不实际修改文件,可以加 --dry-run 参数:

codex exec "分析当前仓库的架构,指出潜在问题" --dry-run

8.4 查看详细日志

遇到问题时开启调试日志:

codex exec "任务描述" --debug

9. 总结

ChatGPT Plus 与 Pro 订阅为 Codex 提供了不同级别的算力与上下文支持,而 Codex 本身则把大模型的能力真正落地到了工程实践中。从本文的示例可以看到,Codex 可以完成:

  • 从零生成带测试的完整工具模块;
  • 跨文件执行仓库级重构;
  • 为已有代码自动补齐边界测试;
  • 通过 GitHub Actions 接入 CI/CD,实现自动化代码审查与 Bug 修复。

建议你从一个小型项目开始,先让 Codex 帮你写测试,再逐步尝试重构和 CI 集成。用得越深,你会越能感受到「AI 结对编程」带来的效率提升。

Logo

AtomGit AI 社区提供模型库、数据集、Agent、Token等资源

更多推荐