Snakemake规则追加结果至已有输出文件失败,如何解决?
解决Snakemake中Amend规则无法执行追加操作的问题
问题场景
构建Snakemake流程时,Amend规则意图将多个样本的统计文件、SNV文件和共识序列文件追加到对应的汇总输出文件中,但运行时系统返回Nothing to be done,无法执行追加操作。尝试过dynamic()标记输出、在shell末尾添加touch命令均无效。
规则代码:
rule Amend: input: Genome_stats = expand("global_temp_workspace/result/{sample}.Genome.stats.tsv", sample= sampleID), GenomeSNV = expand("global_temp_workspace/result/{sample}.Genome.SNVs.tsv", sample= sampleID), GenomesConsensus = expand("global_temp_workspace/analysis/{sample}.renamed.consensus.fasta", sample= sampleID), output: Genome_stats="global_temp_workspace/result/Genome.stats.tsv", GenomeSNV="global_temp_workspace/result/Genome.SNVs.tsv", GenomesConsensus="global_temp_workspace/result/Genomes.consensus.fasta" threads: workflow.cores shell: """ cat {input.Genome_stats} | tail -n +2 >> {output.Genome_stats} ;\ cat {input.GenomesConsensus} >> {output.GenomesConsensus} ;\ cat {input.GenomeSNV} | tail -n +2 >> {output.GenomeSNV} ;\ """
运行日志:
$ time snakemake --snakefile V2.5.smk --cores all Building DAG of jobs... Nothing to be done. Complete log: .snakemake/log/2023-02-15T123050.937009.snakemake.log real 0m1.022s user 0m2.744s sys 0m2.797s
问题原因
Snakemake的核心调度逻辑基于文件时间戳对比:如果输出文件已存在,且所有输入文件的修改时间都早于输出文件,就会判定任务已完成,无需执行。
追加操作属于增量更新,不会改变Snakemake对输出文件的依赖判断逻辑——只要输出文件存在且比输入新,就会跳过任务。dynamic()已被Snakemake废弃,touch仅更新文件时间戳,未从根本上调整依赖关系,因此无法解决问题。
解决方案
方法1:将输出文件加入输入依赖
把汇总输出文件本身作为输入项加入规则,让Snakemake意识到输出文件的状态会影响任务执行,每次运行都会触发追加操作。同时处理输出文件不存在的初始场景,确保表头正确写入:
rule Amend: input: Genome_stats = expand("global_temp_workspace/result/{sample}.Genome.stats.tsv", sample= sampleID), GenomeSNV = expand("global_temp_workspace/result/{sample}.Genome.SNVs.tsv", sample= sampleID), GenomesConsensus = expand("global_temp_workspace/analysis/{sample}.renamed.consensus.fasta", sample= sampleID), # 引入输出文件作为输入,触发增量更新判断 existing_stats = "global_temp_workspace/result/Genome.stats.tsv", existing_snv = "global_temp_workspace/result/Genome.SNVs.tsv", existing_consensus = "global_temp_workspace/result/Genomes.consensus.fasta" output: Genome_stats="global_temp_workspace/result/Genome.stats.tsv", GenomeSNV="global_temp_workspace/result/Genome.SNVs.tsv", GenomesConsensus="global_temp_workspace/result/Genomes.consensus.fasta" threads: workflow.cores shell: """ # 初始场景:如果汇总统计文件不存在,先写入第一个样本的表头 if [ ! -f {output.Genome_stats} ]; then head -n 1 {input.Genome_stats[0]} > {output.Genome_stats} fi # 追加所有样本的内容(跳过表头) cat {input.Genome_stats} | tail -n +2 >> {output.Genome_stats} # 共识序列直接追加,无需处理表头 cat {input.GenomesConsensus} >> {output.GenomesConsensus} # 处理SNV文件的表头写入 if [ ! -f {output.GenomeSNV} ]; then head -n 1 {input.GenomeSNV[0]} > {output.GenomeSNV} fi cat {input.GenomeSNV} | tail -n +2 >> {output.GenomeSNV} """
方法2:强制运行规则(临时方案)
如果仅需临时触发一次追加操作,可使用--force参数指定运行Amend规则:
snakemake --snakefile V2.5.smk --cores all Amend --force
该方法适合单次调试,不建议作为流程的常规配置。
关键说明
- 方法1通过调整依赖关系,让Snakemake正确识别增量更新的需求,是符合Snakemake调度逻辑的长期解决方案。
- 处理表头写入的判断逻辑,确保第一次运行时汇总文件能生成完整的结构,避免后续追加重复表头。
内容的提问来源于stack exchange,提问作者Alhu.A
相关产品推荐
相关产品推荐

