Snakefile文件重命名字典映射问题:为何仅第三种写法生效?
Snakemake文件重命名规则失效原因解析
需求:通过字典{"out": "in"}将文件in复制为out,以下是三种写法的表现及原因分析:
失效代码#1
rename = {"out": "in"} def mapFile(wildcards): print ('wc:',wildcards.rr) file = rename[wildcards.rr] return (file) rule all: input: expand("{rr}", rr = list(rename.keys())) rule rename: input: mapFile output: "{rr}" shell: "cp {input} {output}"
报错信息:
Building DAG of jobs... wc: out wc: in InputFunctionException in rule rename in file /Users/geo/Desktop/tmp/q.snakefile, line 12: Error: KeyError: 'in' Wildcards: rr=in Traceback: File "/Users/geo/Desktop/tmp/q.snakefile", line 5, in mapFile (rule rename, line 19, /Users/geo/Desktop/tmp/q.snakefile)
疑问:明明只展开了字典的key(out),但通配符rr却同时出现in和out,触发KeyError。
失效代码#2
rename = {"out": "in"} rule all: input: expand("{rr}", rr = list(rename.keys())) rule rename: input: lambda wildcards: rename[wildcards.rr] output: "{rr}" shell: "cp {input} {output}"
报错信息:
Building DAG of jobs... InputFunctionException in rule rename in file /Users/geo/Desktop/tmp/q.snakefile, line 12: Error: KeyError: 'in' Wildcards: rr=in Traceback: File "/Users/geo/Desktop/tmp/q.snakefile", line 15, in <lambda> (rule rename, line 19, /Users/geo/Desktop/tmp/q.snakefile)
生效代码#3
rename = {"out": "in"} rule all: input: expand("{rr}", rr = list(rename.keys())) rule rename: input: lambda wildcards: rename.get(f"{wildcards.rr}", "") output: "{rr}" shell: "cp {input} {output}"
核心原因:Snakemake的通配符反向推断机制
Snakemake构建DAG时,不仅会从rule all的目标反向推导待生成文件,还会尝试匹配规则的输入文件是否需要由其他规则生成:
- 当规则
rename的输入是in时,Snakemake会把in当作潜在的输出文件,尝试用同一个rename规则生成它——此时通配符rr被赋值为in,而字典中无此key,rename[wildcards.rr]触发KeyError。 - 代码#3用
rename.get(),当rr=in时返回空字符串,Snakemake会认为空输入是外部已存在的文件,不会尝试生成它,停止反向推断,因此避免了错误。
代码1、2失效的本质
- 代码1的
mapFile函数在Snakemake反向推断in作为输出时被调用,wildcards.rr=in导致字典key查找失败。 - 代码2的lambda函数逻辑与代码1一致,同样因
rr=in触发KeyError。
代码3生效的关键
rename.get(f"{wildcards.rr}", "")在匹配不到key时返回空字符串,触发Snakemake对“外部输入文件”的判定,终止无效的反向推断流程,从而正常执行目标任务。
内容的提问来源于stack exchange,提问作者hud
相关产品推荐
相关产品推荐

