Python调用R脚本遇FileNotFoundError:导入R库时subprocess调用失败
看起来你的核心问题是导入limma库后R脚本执行失败,导致subprocess.call返回非零值(非零代表执行出错),自然无法生成output.csv,进而Python读取时报错。虽然subprocess.call是阻塞式调用(必须等R脚本执行完才会继续执行第4行),但如果R脚本执行失败中途退出,就不会生成目标文件。下面给你几个具体的排查方向:
1. 捕获R脚本的错误输出,定位具体失败原因
默认情况下subprocess.call不会捕获R脚本的错误信息,你根本不知道R脚本在执行时到底出了什么问题。建议修改Python代码,改用subprocess.run来捕获标准输出和错误输出:
import subprocess import pandas as pd import os print("Python当前工作目录:", os.getcwd()) result = subprocess.run( ["/usr/bin/Rscript", "--vanilla", "script.R"], capture_output=True, text=True ) print("R脚本返回码:", result.returncode) print("R脚本标准输出:\n", result.stdout) print("R脚本错误输出:\n", result.stderr) # 只有返回码为0时才尝试读取文件 if result.returncode == 0: df = pd.read_csv("output.csv") else: print("R脚本执行失败,无法读取output.csv")
运行这段代码后,错误输出里会明确告诉你R脚本哪里出问题——比如limma库没安装、依赖缺失,或者路径错误。
2. 确认subprocess调用的R环境与手动运行的一致
你提到单独运行R代码没问题,但要确认系统中多个R版本的可能性:手动运行的R可能不是/usr/bin/Rscript这个路径的版本。可以在终端直接执行这条命令,模拟subprocess的调用环境:
/usr/bin/Rscript -e "library(limma); print('limma加载成功')"
如果这条命令报错,说明这个R版本确实没装limma,直接用这个路径的R安装即可:
/usr/bin/Rscript -e "install.packages('limma', repos='https://cloud.r-project.org/')"
3. 检查工作目录一致性
有时候Python脚本的工作目录和R脚本执行时的工作目录不一致,可能导致input.csv找不到(虽然你说单独运行没问题,但导入库后可能触发了路径相关的隐性错误)。可以在R脚本开头添加一行打印当前工作目录的代码:
print("R当前工作目录:", getwd()) library(limma) df <- read.csv("input.csv") df <- normalizeCyclicLoess(df) write.csv(df, "output.csv")
对比Python和R的工作目录,如果不一致,建议在R脚本中使用绝对路径读取和写入文件,比如:
input_path <- "/path/to/your/input.csv" output_path <- "/path/to/your/output.csv" df <- read.csv(input_path) # ...处理逻辑... write.csv(df, output_path)
4. 检查limma的依赖包是否完整
limma依赖一些其他的Bioconductor包,有时候加载limma失败是因为依赖包缺失。可以在R脚本中显式检查依赖:
if (!requireNamespace("limma", quietly = TRUE)) { stop("limma包未安装,请先安装") } library(limma)
如果是依赖问题,你需要安装对应的依赖包,或者直接用Bioconductor的安装方式重新安装limma:
/usr/bin/Rscript -e "if (!requireNamespace('BiocManager', quietly = TRUE)) install.packages('BiocManager'); BiocManager::install('limma')"
5. 排除R配置文件的干扰
虽然你用了--vanilla参数,但可以再加强参数,确保R在完全干净的环境下执行,避免用户配置文件的干扰:
subprocess.run( ["/usr/bin/Rscript", "--vanilla", "--no-site-file", "--no-init-file", "script.R"], capture_output=True, text=True )
内容的提问来源于stack exchange,提问作者Ankit Kumar

