你让 ChatGPT 处理一个 200MB 的 CSV、拟合一个模型、再画残差图。二十秒过去,响应单元变红:“The code execution timed out” 或者 “Sandbox terminated. Retrying…”。模型重试一次,撞上同样的墙,然后干脆改打印伪代码,不再实际运行。Code Interpreter(在部分入口里叫 Advanced Data Analysis)是把你的 Python 跑在每条消息独立的临时容器里 —— 通常每个 cell 有 60-120 秒的硬墙钟上限,以及很紧的内存和 CPU 限制。大多数超时不是 “ChatGPT 坏了”,而是一个 cell 想一口气干完所有事,把整个 dataframe 全部塞进内存,或者卡在沙盒根本走不出去的网络调用上。
常见原因
按实际会话中遇到的频率排序。
1. 单个 cell 想把端到端的活全干完
模型写了一个巨型 cell:读 CSV → 清洗 → 特征工程 → 训练 → 交叉验证 → 画图。哪怕只是一个 50MB 的文件,这个组合也经常突破 60 秒上限。Code Interpreter 不会流式返回中间结果,cell 一挂中间状态就全没了。
怎么判断:出错的 cell 超过约 40 行 Python,里面有多个对 dataframe 的 for 循环,且至少出现一次 fit / cross_val_score 调用。
2. 沙盒里发起了网络请求
绝大多数账号下,沙盒默认是离线的。requests.get("https://api.example.com/...")、yfinance.download(...) 这种写法不会立即失败 —— 它会一直挂到 60 秒看门狗把它杀掉。pip install 在限制环境下也是同样表现。
怎么判断:cell 里 import 了 requests / urllib / httpx / yfinance / pandas_datareader,或者直接 pd.read_csv("http...")。超时之前没有任何进度输出。
3. 没等到时间到,内存先爆了
大表 join 或者宽表 df.pivot() 容易突破约 1-2GB 的 RAM 上限。内核被 OOM-killed,ChatGPT 给你显示的是一个通用的超时提示 —— 哪怕实际上根本没耗多少时间。
怎么判断:cell 不到 10 秒就挂出超时。换成小切片 (df.head(1000)) 再跑就秒回。
4. 在宽 dataframe 上用 pandas 的链式 lambda
df.apply(lambda row: ...) 跑 100 万+ 行就是单线程纯 Python。向量化版本 2 秒搞定,lambda 版本 60 秒超时。模型经常写 lambda 版本,因为代码更短。
怎么判断:对超过 ~10 万行的 frame 用了 .apply(lambda ...) 或 .iterrows()。
5. 上传文件在 cell 之间丢了,代码每次都重新读
新的对话回合可能会拉起一个全新的沙盒。如果第 3 轮要用第 1 轮上传的文件,模型可能每轮都重新读、重新解析、重新生成特征 —— 把超时预算全浪费在重做准备工作上。参考 ChatGPT 附件在刷新后丢失 里关于沙盒状态的细节。
怎么判断:每个 cell 开头都是 pd.read_excel("/mnt/data/<file>.xlsx") 加新鲜的 df.head()。之前 cell 里的变量全部不见。
6. 画图时点数太多
matplotlib 散点图画 50 万+ 个点,要在沙盒 CPU 上把整个图序列化成 PNG。光这一步就能吃掉 30 秒以上。
怎么判断:超时前最后能看到的动作是 plt.show() 或者 sns.scatterplot。把点数砍到 5000 就立刻不超时了。
开始之前
- 确认你的套餐 —— Free 的沙盒限制比 Plus / Team / Pro / Enterprise 都更紧。
- 看清楚超时是确定性的(每次都在同一个 cell)还是偶发的(有时能跑完)。
- 重新提示之前先把出问题的 cell 代码留底,ChatGPT 经常在重试时改写代码,你就丢失证据了。
- 检查上传文件的体积 —— 默认下,任何超过 ~100MB 的文件都有风险。
需要收集的信息
- 出现的具体报错文本(“execution timed out”、“sandbox terminated”、“kernel restarted”)。
- 超时前的大约挂钟时间(用秒表 —— 这能区分 OOM 和墙钟超时)。
- Dataframe 形状(
df.shape)和按 dtype 算的内存占用(df.memory_usage(deep=True).sum() / 1e6MB)。 - cell 是否有任何网络 I/O 或
pip install。 - 当前使用的模型(GPT-5.5、GPT-5.4 等) —— 模型选择会影响 planner 怎么把活拆进各个 cell。
一步一步修
按 ROI 从高到低排。
第 1 步:逼模型把活拆成有 checkpoint 的多个 cell
在提示里加一段:
分多个 cell 跑这次分析,每个 cell 控制在 30 秒以内:
Cell 1: 读取并检查文件,只打印 shape 和 dtypes。
Cell 2: 清洗并 downcast,把 df 保存到 /mnt/data/clean.parquet。
Cell 3: 特征工程,保存 features.parquet。
Cell 4: 训练并评估,打印指标。
Cell 5: 只画一张图。
不要合并 cell。中间状态用 parquet 文件持久化。
这能把一个 120 秒的巨型 cell 拆成五个 20 秒的小 cell,中间的 parquet 文件还能熬过沙盒重启。
第 2 步:在重计算之前先 downcast 和切片
在训练或 pivot 之前,先把 dataframe 压小:
import pandas as pd
df = pd.read_csv("/mnt/data/input.csv")
for col in df.select_dtypes("float64"):
df[col] = pd.to_numeric(df[col], downcast="float")
for col in df.select_dtypes("int64"):
df[col] = pd.to_numeric(df[col], downcast="integer")
for col in df.select_dtypes("object"):
if df[col].nunique() / len(df) < 0.5:
df[col] = df[col].astype("category")
print(df.memory_usage(deep=True).sum() / 1e6, "MB")
1.8GB 的 frame 经常能压到 300MB。同一个 cell 立刻就装得下了。
第 3 步:把 apply(lambda) 换成向量化操作
直接要求模型:
重写这个 cell,不要用 .apply(),也不要用 .iterrows()。只用向量化的
pandas / numpy 操作。如果某一步无法向量化,就在 df.sample(50_000)
上做,并解释 trade-off。
很多时候,这一次重写就能把 90 秒超时变成 3 秒跑完。
第 4 步:给 matplotlib 限制点数
任何在大 frame 上的散点图都这么写:
sample = df.sample(min(5000, len(df)), random_state=0)
plt.scatter(sample["x"], sample["y"], s=4, alpha=0.4)
plt.show()
或者改用 hexbin / 2dhist,先聚合再渲染。渲染时间从 30 秒掉到 1 秒以内。
第 5 步:把中间状态持久化到 /mnt/data/
沙盒工作目录 /mnt/data/ 在同一对话内多数沙盒重启之间能保留下来。每完成一个重计算步骤就保存:
df_clean.to_parquet("/mnt/data/clean.parquet")
features.to_parquet("/mnt/data/features.parquet")
下一个 cell 用 df = pd.read_parquet(...) 起步 —— 亚秒级。哪怕第 4 个 cell 超时,前面 1-3 个 cell 的成果都还在。
第 6 步:把网络调用挪出沙盒
如果脚本需要外部数据,不要让 Code Interpreter 自己去抓。做法:
- 自己在本地下好数据(curl、浏览器都行)。
- 把文件上传到对话里。
- 让模型只从
/mnt/data/<file>读取。
对于需要付费墙或登录的来源,可以参考 ChatGPT 联网搜索被付费墙站点拦截 —— Code Interpreter 受同样的边界约束。
第 7 步:实在不行就把沙盒重启一遍
在新一轮对话里:
重置 Python 沙盒。在新 cell 里 print("ok") 确认,
然后重新加载 /mnt/data/clean.parquet。
旧内核的残留状态(挂住的线程、上一轮泄漏的文件句柄)确实是性能下降的真实原因,换个新内核往往立马变快。
验证
- 之前出错的 cell 现在能完整跑完,输出直接显示在下面。
- 整个分析的总挂钟时间在沙盒预算内还有富余(目标:每个 cell 不超过 30 秒)。
- 在新的对话里重跑同一个提示能复现成功 —— 证明不是内核偶尔抽风。
- downcast 之后内存占用低于 500MB(之前要 1.5GB+)。
长期预防
- 任何超过 50MB 的文件,对话第一步就让模型先打印
shape、dtypes,并先规划 downcast 方案,再动数据。 - 把”每个 cell 只做一件事”写进你的提示模板。读取、清洗、join、建模、绘图都各占一个 cell。
- 任何超过 10 秒的步骤之后都要持久化到 parquet;把沙盒当作可丢弃的临时资源。
- 重复性的工作流优先用本地 Jupyter / Colab,只用 ChatGPT 生成和审阅代码。
- 永远不要让模型在沙盒里写
requests.get(...),要么提前下好,要么干脆不调。 - 用 Advanced Data Analysis 处理超大文件时,先把上传切块(
split -n l/4 big.csv),分块处理。
常见坑
- 不给具体预算就说”让它更快”,换来的只是边角的微调,而不是结构性重组。
- 同一个失败提示重跑 5 次,把消息上限耗光 —— 参考 ChatGPT 消息上限触发。
- 以为
pip install <pkg>是免费的;某些套餐里它会触发沙盒刷新,耗 10-20 秒。 - 为了”精度”硬要画 100 万个原始点 —— 你的眼睛区分不出 5000 和 100 万,但沙盒能。
- 忘了
/mnt/data/在开新对话时会被清空。文件在同一线程内能存,跨线程不行。 - 看到 “completed successfully” 就当成功,实际并没有真的画出图或表 —— 一定要看输出 cell。
FAQ
Q: 60 秒超时在所有套餐上一样吗?
不一样。Free 最紧,Plus / Team 较宽,Pro 和 Enterprise 上限最高但也不是无限。沙盒规格没有公开文档,而且会变 —— 不管你哪个套餐,单个 cell 超过 30 秒都要当作有风险。
Q: 能直接调大超时吗?
不能。要做的是结构调整:文件更小、downcast、向量化、拆 cell、持久化 parquet。真正有用的旋钮只有升级到 Pro / Enterprise,但它只是抬高上限,不会消除。
Q: 我本地 3 秒能跑完的 cell,在 ChatGPT 里就超时,为什么?
沙盒 CPU 核心数比你笔记本少,没有 GPU,磁盘也更慢。被单线程 Python(lambda、循环)主导的运算上限低得多。改成向量化以后差距通常就消失了。
Q: Advanced Data Analysis 和 Code Interpreter 是同一个限制吗?
是 —— 它们就是同一个功能在不同入口下的两个名字。沙盒、包、超时行为完全一致。
Q: 我上传的文件中途消失了,是超时引起的吗?
不是,那是另一个沙盒重启问题。参考 ChatGPT 文件从对话中消失 —— 重新上传,在任何重计算步骤之前先持久化到 parquet。