Snakemake规则输出中能否使用含通配符的参数作为变量?
在Snakefile中用通配符定义参数并复用为输出路径的方法
想在Snakefile的规则里,用通配符定义params中的前缀,再把这个前缀参数复用在output的路径定义里,避免重复编写相同的路径前缀。尝试了如下写法:
rule train_stuff: input: "input.{lang}.txt" params: prefix="model.{lang}" output: "{params.prefix}.npz", "{params.prefix}.vocab", "{params.prefix}.some_other_auxiliary_output" shell: """ # ... 生成三个输出文件的逻辑 ... touch {output[0]} touch {output[1]} touch {output[2]} """
但这段代码会触发以下错误:
WildcardError in rule train_stuff in file (...)/Snakefile, line 2: Wildcards in input files cannot be determined from output files: 'lang'
错误原因
报错的核心是Snakemake的依赖解析逻辑:它需要从输出路径的通配符反向推导输入路径的通配符。原写法中,输出路径用{params.prefix}包裹了前缀,导致Snakemake无法从输出路径里识别出lang这个通配符,自然没法对应到输入的input.{lang}.txt。
解决方案
方案1:用expand()函数简化输出路径定义
如果只是想避免重复写前缀,最简洁的方式是用expand()函数一次性生成所有输出文件,无需借助params:
rule train_stuff: input: "input.{lang}.txt" output: expand("model.{lang}.{ext}", ext=["npz", "vocab", "some_other_auxiliary_output"]) shell: """ # 直接用{output}批量引用所有输出文件 touch {output} """
方案2:结合lambda函数与params复用前缀
如果确实需要通过params统一管理前缀(比如后续shell命令里也要复用),可以用lambda函数基于wildcards生成前缀,让Snakemake能识别输出中的通配符:
rule train_stuff: input: "input.{lang}.txt" params: # 用lambda从wildcards中获取lang生成前缀 prefix=lambda wildcards: f"model.{wildcards.lang}" output: "{params.prefix}.npz", "{params.prefix}.vocab", "{params.prefix}.some_other_auxiliary_output" shell: """ # shell中也可以直接复用params.prefix touch {params.prefix}.npz touch {params.prefix}.vocab touch {params.prefix}.some_other_auxiliary_output """
这里用lambda函数替代直接写"model.{lang}",让params的前缀动态依赖wildcards,Snakemake就能通过输出路径反向关联到输入的lang通配符,解决报错问题。
内容的提问来源于stack exchange,提问作者Jindra Helcl
相关产品推荐
相关产品推荐

