使用Snakemake运行Notebook时如何加载同目录数据文件
问题复现
项目文件结构:
processing_step_1/process.ipynb:数据处理Notebook,核心读取代码如下
with open('input.csv') as infile: for line in infile: print(line)
processing_step_1/input.csv:同目录下的待处理数据,内容为
one,two,three 1,2,3
- 根目录
Snakefile规则配置
rule process_data: input: "processing_step_1/input.csv", notebook: "processing_step_1/process.ipynb"
运行表现:
- 交互式打开Notebook、或在项目目录执行
jupyter nbconvert --execute --to notebook processing_step_1/process.ipynb时,代码运行正常,此时默认工作目录为Notebook所在的processing_step_1,相对路径可直接定位到输入文件。 - 执行
snakemake -c1调度运行时抛出文件不存在错误:
FileNotFoundError: [Errno 2] No such file or directory: 'input.csv'
报错原因
Snakemake执行Notebook类型规则时,会先将Notebook复制到.snakemake/scripts下的临时目录,再执行临时副本,默认工作目录为项目根目录,和手动运行Notebook时的工作目录不一致,导致相对路径匹配失败。从执行日志可看到实际运行的是临时副本:
Command 'set -euo pipefail; jupyter-nbconvert --log-level ERROR --execute --to notebook --ExecutePreprocessor.timeout=-1 /path/to/project/.snakemake/scripts/tmp9mmr8k20.process.ipynb' returned non-zero exit status 1.
解决方案
以下方案均满足要求:支持Notebook脱离Snakemake独立运行,无额外侵入性逻辑。
方案1:仅修改Snakefile配置(优先推荐,零改动Notebook代码)
不需要修改Notebook内的任何业务代码,仅在规则配置中通过notebook_kws向nbconvert执行器传参,指定单条规则的Notebook运行工作目录即可。
Snakemake调用nbconvert执行Notebook时,支持透传参数给ExecutePreprocessor,其中cwd参数可直接指定Notebook执行时的工作目录,和手动运行时的目录保持一致。修改后的规则配置如下:
rule process_data: input: "processing_step_1/input.csv", notebook: "processing_step_1/process.ipynb", notebook_kws: {"ExecutePreprocessor": {"cwd": "processing_step_1"}}
该配置为规则级别,仅对当前process_data规则生效,不会影响其他规则的运行逻辑。配置生效后,Notebook执行时的工作目录会被自动切换到processing_step_1,原有相对路径可正常生效,和交互式运行、手动执行nbconvert的行为完全一致。
方案2:轻量调整Notebook路径逻辑
如果不方便修改Snakefile配置,可在Notebook开头增加少量通用路径判断逻辑,仅在Snakemake环境下读取调度传入的文件路径,独立运行时保持原有逻辑不变:
from pathlib import Path # 兼容Snakemake调度、独立运行两种场景 if "snakemake" in globals(): input_file = Path(snakemake.input[0]) else: input_file = Path("input.csv") with open(input_file) as infile: for line in infile: print(line)
该逻辑不会破坏Notebook的独立运行能力,仅在Snakemake调度场景下才会读取内置的规则输入路径,代码侵入性极低。
内容的提问来源于stack exchange,提问作者hfs

