Snakemake触发MissingInputException后,能否查看依赖栈追踪?
在Snakemake触发MissingInputException时,系统会输出涉事规则的输出文件、wildcards以及"受影响文件"。这类问题通常分两种情况:
- 受影响文件列表正确,但缺少匹配规则、规则格式错误或文件实际不存在
- wildcards匹配不符合预期,生成了错误的文件名
第一种情况容易调试,第二种在规则数量多、DAG复杂时定位难度极大——我们需要获取从rule all的输入文件开始,到触发异常的完整依赖栈追踪,以此明确哪条规则、哪个wildcards匹配出了问题。
场景示例
比如我们想通过this_is.tsv、an_input_file.tsv生成this_is_an_input_file-summary.txt,编写的规则如下:
rule all: input: 'this_is_an_input_file-summary.txt' rule A: input: '{prefix}.tsv' output: '{prefix}-summary.txt' rule B: input: '{part1}.tsv', '{part2}.tsv' output: '{part1}_{part2}.tsv'
这里rule B会递归匹配,试图寻找this.tsv、is.tsv等不存在的文件,最终触发MissingInputException。当规则埋在数百条里、DAG结构复杂时,怎么打印完整的依赖链?
解决方案
1. 启用详细日志参数
运行Snakemake时添加--verbose(简写-v)或--debug参数,会输出完整的依赖解析过程,包括每个文件的匹配路径、规则调用序列:
snakemake --verbose
输出中会清晰展示反向推导的步骤:从this_is_an_input_file-summary.txt匹配rule A的{prefix}-summary.txt,得到prefix=this_is_an_input_file;接着寻找this_is_an_input_file.tsv时匹配rule B的{part1}_{part2}.tsv,拆分出part1=this_is、part2=an_input_file;随后继续递归拆分this_is.tsv为part1=this、part2=is,最终因找不到对应文件触发异常。
2. 自定义依赖回溯逻辑(进阶)
如果默认日志不够直观,可以通过Snakemake API编写自定义脚本,捕获MissingInputException后反向遍历DAG依赖链:
from snakemake import Workflow from snakemake.exceptions import MissingInputException try: # 初始化工作流 workflow = Workflow(snakefile="Snakefile") workflow.execute() except MissingInputException as e: print("=== 依赖栈追踪 ===") current_file = e.missing_input[0] # 反向遍历依赖链 while current_file in workflow.dag.dependencies: dep_node = workflow.dag.dependencies[current_file] rule = dep_node.rule print(f"文件 `{current_file}` 由规则 `{rule.name}` 生成") print(f" 规则输入模板: {rule.input}") print(f" 匹配到的wildcards: {dep_node.wildcards}") # 取第一个输入文件继续回溯(需根据实际场景调整多输入逻辑) current_file = next(iter(dep_node.input))
这个脚本会从缺失的文件开始,逐层打印生成它的规则、wildcards匹配结果,直到追溯到rule all的输入。
3. 打印待执行命令辅助验证
添加--printshellcmds参数,会输出每个规则准备执行的命令,能直接看到wildcards替换后的实际文件名,快速定位哪一步生成了错误路径:
snakemake --printshellcmds
内容的提问来源于stack exchange,提问作者krumpelstiltskin

