Snakemake如何通过文件名通配符索引实现单条规则迭代执行
Snakemake迭代规则实现文件逐次修改的方案
问题复现
当前实现需求:
- data目录下已存在空文本文件
basic_0 - 执行命令
snakemake data/basic_<x>.txt --cores 1(x为任意正整数)时,规则迭代执行x次,每次调用addHi.py向文件新增一行内容为"Hi"的记录,最终data/basic_x.txt包含x行"Hi"
初始编写的Snakefile如下:
rule iterative_addHi: input: "data/basic_{iter}.txt" output: "data/basic_{iter+1}.txt" shell: "python addHi.py {input} {output}"
执行snakemake data/basic_5.txt --cores 1时抛出报错:
MissingRuleException: No rule to produce data/basic_5.txt (if you use input functions make sure that they don't raise unexpected exceptions).
尝试过将通配符通过int()转整数完成加1运算后再用str()转回字符串的方案,问题未解决。
报错根因
- Snakemake的文件路径通配符默认按字符串解析,不支持直接在输出路径模板中写算术表达式,
{iter+1}这类写法无法被规则识别,导致目标文件无法匹配到对应生成规则 - Snakemake构建任务DAG时是从目标文件倒推依赖,原规则的通配符定义在输入侧,输出侧包含运算逻辑,无法从目标文件名(比如basic_5.txt)反推整条依赖链。
修正后可运行代码
# 声明迭代起点文件 rule basic_seed: output: "data/basic_0.txt" # 若文件已存在,touch不会覆盖原有内容,仅标记该文件为合法产出 touch: True rule iterative_addHi: output: "data/basic_{iter}.txt" input: # 从目标文件的通配符倒推前置依赖:编号减1的文件 lambda wc: f"data/basic_{int(wc.iter) - 1}.txt" shell: "python addHi.py {input} {output}"
关键注意点
- 通配符必须定义在
output块中,Snakemake只能通过输出路径的模式匹配捕获通配符值,不要在输出路径中写任何运算逻辑 - 依赖文件的路径计算放在
input块中,通过lambda表达式接收捕获到的通配符对象wc,做数值运算后拼接出前置依赖路径,Snakemake会自动沿着basic_5.txt -> basic_4.txt -> ... -> basic_0.txt的路径构建完整执行链 - 必须显式声明迭代起点
basic_0.txt的对应规则,否则Snakemake解析到最后一个依赖时会因为找不到生成规则报错。
内容的提问来源于stack exchange,提问作者jabbo12
相关产品推荐
相关产品推荐

