如何避免Snakemake因基准文件缺失重复执行规则?
Snakemake:忽略缺失基准文件以避免规则重复执行
我使用Snakemake 8.23.2版本时遇到问题:仅因基准文件缺失,即使主输出文件已存在,规则仍会被重新执行。以下是具体场景、异常表现及解决方案:
场景与Snakefile代码
我的Snakefile定义了一个带动态基准文件的规则:
from datetime import datetime NOW = datetime.now().strftime("%Y%m%d-%H%M%S") rule all: input: "test" rule test: output: "test" benchmark: "benchmark/" + NOW + ".tsv" shell: """ sleep 3 touch {output} """
异常表现
首次运行snakemake test时规则正常执行,但后续运行时,Snakemake会因为基准文件缺失触发规则重新执行:
❯ snakemake test [...] [Fri Oct 25 15:22:20 2024] localrule test: output: test jobid: 0 benchmark: benchmark/20241025-152220.tsv reason: Missing output files: benchmark/20241025-152220.tsv resources: tmpdir=/tmp [...]
预期行为
只要主输出文件存在,无论基准文件是否存在,Snakemake都应判定规则已完成:
❯ snakemake all Assuming unrestricted shared filesystem usage. Building DAG of jobs... Nothing to be done (all requested files are present and up to date).
已尝试方案
曾使用--rerun-triggers选项,但未解决问题。
解决方案
要让Snakemake忽略缺失的基准文件,推荐以下两种方法:
方法1:标记基准文件为可选(推荐)
在规则的benchmark定义中使用benchmark()函数并添加optional=True参数,标记该基准文件为可选。这样Snakemake会跳过对基准文件的缺失检查,仅在主输出文件需要更新时才执行规则:
rule test: output: "test" benchmark: benchmark("benchmark/" + NOW + ".tsv", optional=True) shell: """ sleep 3 touch {output} """
该参数从Snakemake 5.10版本开始支持,8.23.2版本完全兼容。添加后,基准文件存在时会正常生成,缺失时不会触发规则重跑。
方法2:自定义执行逻辑(复杂场景适用)
如果需要更灵活的控制,可以将规则逻辑迁移到run函数中,手动检查主输出文件状态,仅在必要时执行任务并生成基准文件:
import os import subprocess from datetime import datetime NOW = datetime.now().strftime("%Y%m%d-%H%M%S") rule all: input: "test" rule test: output: "test" run: if not os.path.exists(output[0]): # 执行原任务逻辑 subprocess.run(f"sleep 3; touch {output[0]}", shell=True) # 生成基准文件 benchmark_path = f"benchmark/{NOW}.tsv" with open(benchmark_path, "w") as f: # 可写入自定义基准数据,例如运行时间 f.write("runtime\t3\n")
这种方式需要将shell命令转换为Python代码,适合需要额外逻辑判断的场景。
内容的提问来源于stack exchange,提问作者ManJi
相关产品推荐
相关产品推荐

