Jupyter Notebook 读取 AnnData 对象时 R kernel 反复退出,如何排查?
结论
仅凭这段代码无法确定 kernel 退出的原因。先检查 R 进程是否因内存限制被终止,再查看是否存在底层库崩溃、文件读取异常或运行环境变化。
脚本过去能运行,说明此前的文件、资源和环境组合可用。当前数据文件、可用内存、软件包或依赖发生变化,都可能导致同一段代码失败。重启 kernel 后问题仍然复现,需要保留退出日志继续排查。
1. 先区分 R 报错和进程直接退出
如果 Notebook 中出现普通的 R 错误信息,且 kernel 仍可执行其他命令,可以从错误信息入手。如果 kernel 直接消失或自动重启,应先查看启动 Jupyter 的终端输出、Jupyter 服务日志和运行平台提供的进程退出记录。
重点寻找以下线索:
out of memory、OOM或系统明确记录的内存不足终止事件。segmentation fault、segfault或其他原生代码崩溃信息。- Python、HDF5 或其他依赖加载失败的具体信息。
这些线索还不能确定当前问题的原因。单独出现 Killed 也不足以确认是内存不足,需要结合系统或平台日志判断。
如果 R 进程被操作系统终止,或因底层崩溃而退出,普通的 tryCatch() 无法使其恢复。此时应查看进程外部的日志。
2. 在读取前确认文件和函数来源
先在新启动的 kernel 中运行以下检查,再执行读取操作:
file <- "../adata/adata_celltypes_labelled_final.h5ad"
getwd()
stopifnot(file.exists(file))
stopifnot(file.access(file, mode = 4) == 0)
normalizePath(file, mustWork = TRUE)
file.info(file)[, c("size", "mtime"), drop = FALSE]
find("readH5AD")
sessionInfo()
相对路径取决于当前工作目录。确认实际读取的是预期文件,并检查文件大小和修改时间是否与之前成功运行时一致。如果有可信的旧副本,可以比较校验值。文件存在且可读,不能证明内部数据完整。
原问题没有提供 readH5AD() 所属的软件包及版本。先确认函数来源,再根据该版本的帮助文档判断读取行为,避免直接套用其他包或其他版本的参数。
3. 检查读取时的内存峰值和资源限制
执行读取操作时,从系统或运行平台观察 R 进程的内存变化。如果 Notebook 运行在容器、作业系统或共享服务器中,还要检查该进程实际受到的内存限制;机器总内存不等于当前任务可用的内存。
use_hdf5=TRUE 的具体作用取决于函数实现。即使它让部分数据使用 HDF5 后端,也不能保证整个读取过程不会出现较高的内存峰值。元数据、格式转换和中间对象仍可能占用内存,磁盘上的文件大小也不能直接代表读取所需内存。
如果日志确认是内存不足,可按顺序处理:
- 在全新会话中只加载必要的软件包并读取文件。
- 关闭不需要的计算任务,或提高当前任务的内存配额。
- 如果软件包支持,考虑分块读取或减少读取内容;具体参数以已安装版本的文档为准。
不要把切换为 use_hdf5=FALSE 当作通用修复,它可能改变数据加载方式并增加内存需求。
4. 在 Notebook 外复现并保存日志
准备一个最小脚本,例如 reproduce.R。脚本先加载原 Notebook 使用的软件包,再记录环境并执行读取:
# 在这里添加原 Notebook 使用的 library(...) 语句
print(sessionInfo())
print(find("readH5AD"))
file <- "../adata/adata_celltypes_labelled_final.h5ad"
stopifnot(file.exists(file))
sce <- readH5AD(file, use_hdf5 = TRUE, verbose = TRUE)
从终端运行并保存输出:
Rscript reproduce.R > readH5AD.log 2>&1
运行时应尽量保持相同的 R 版本、软件包库、工作目录和依赖环境,否则两次结果不便直接比较。verbose=TRUE 可能提供更多读取进度,但进程突然退出时,日志也可能不完整。
如果进程在终端中同样退出,应继续检查文件、资源和底层依赖。如果只在 Notebook 中发生,则重点比较 kernel 使用的 R 路径、环境变量、软件包库和资源配额。
5. 用对照读取缩小范围
在同一环境下,分别读取一个较小且已知可用的 .h5ad 文件和当前文件。如果小文件成功、当前文件失败,仍需区分文件内容问题与数据规模带来的资源压力。
如果条件允许,再用已知可用的环境读取当前文件,或在当前环境中读取此前成功的文件。每次只改变一个条件,并保留环境信息和退出日志。不要一开始同时升级多个软件包,否则会增加定位难度。
进一步判断需要 readH5AD() 的包名和版本、sessionInfo() 输出、文件大小、进程内存变化,以及 kernel 退出前后的日志。根据这些证据,再选择增加内存、修复依赖或重新获取数据文件等具体处理方式。
备注:内容仅供参考。
