You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Snakemake动态输入输出规则链报错:通配符无法从输出确定

解决Snakemake动态输出文件后续规则链的wildcard匹配问题

我太懂你这个困扰了——当规则a动态生成一批{id}.txt文件后,想让后续的规则b自动逐个处理这些文件,却被"wildcards in input files cannot be determined from output files:"这个报错卡住。其实这个需求完全是支持的,只是Snakemake需要更明确的线索来追踪这些动态生成的wildcard值,而不是直接用dynamic()在后续规则里引用。

为什么会报错?

Snakemake在启动时就需要构建完整的依赖关系图,它得提前知道所有wildcard的可能取值。但你用dynamic('my/path/{id}.txt')作为规则b的输入时,这些{id}的值是规则a运行后才生成的,初始化阶段Snakemake根本没法预判,自然就会报错说无法从输出确定wildcard。

两种解决方案

方案1:提前明确wildcard取值(适用于可预知id的场景)

如果你的{id}取值是可以提前确定的(比如来自配置文件、静态列表,或者能从某个输入文件里提前解析出来),那直接把这些值定义好,用expand()来串联规则就行:

# 提前定义所有可能的id,也可以从文件读取,比如pd.read_csv("ids_list.csv")["id"].tolist()
IDS = ["sample1", "sample2", "sample3"]

# 定义最终目标,让Snakemake知道要生成哪些文件
rule all:
    input:
        expand("processed/{id}.final_result", id=IDS)

rule a:
    input: "my_static_file.txt"
    output: "my/path/{id}.txt"
    shell: """
        # 这里写生成单个{id}.txt的逻辑,比如根据IDS循环生成
        echo "Processing {wildcards.id}" > {output}
    """

rule b:
    input: "my/path/{id}.txt"
    output: "processed/{id}.final_result"
    shell: """
        # 处理每个id对应的输入文件
        cat {input} > {output}
    """

方案2:用Checkpoint处理完全动态的输出(适用于id不可预知的场景)

如果{id}是规则a运行时才动态生成的(比如从输入文件里提取未知数量的id),那Snakemake的checkpoint机制就是专门解决这个问题的——它会先运行checkpoint规则生成动态文件,然后重新构建依赖图,这样就能捕获到新生成的wildcard值了:

# 用checkpoint替代普通规则,标记这是动态生成内容的步骤
checkpoint generate_dynamic_files:
    input: "my_static_file.txt"
    output: directory("my/path")  # 用目录作为输出,告诉Snakemake这里会有动态内容
    shell: """
        # 这里写动态生成文件的逻辑,比如随机生成几个id的文件
        mkdir -p my/path
        echo "Content for id_x" > my/path/id_x.txt
        echo "Content for id_y" > my/path/id_y.txt
        echo "Content for id_z" > my/path/id_z.txt
    """

# 定义一个函数,从checkpoint的输出目录里获取所有生成的文件
def get_dynamic_inputs(wildcards):
    import glob
    # 返回所有生成的txt文件路径
    return glob.glob("my/path/*.txt")

# 用wildcard函数提取每个输入文件对应的id
def extract_id_from_input(input_file):
    # 从路径my/path/id_x.txt里提取id_x
    return input_file.split("/")[-1].split(".")[0]

rule process_dynamic_files:
    input: get_dynamic_inputs
    output: "processed/{id}.final_result"
    # 告诉Snakemake如何从输入文件映射到输出的wildcard
    wildcard_constraints:
        id = extract_id_from_input(input[0])
    shell: """
        cat {input} > {output}
    """

rule all:
    input:
        # 动态获取最终要生成的结果文件路径
        lambda: expand("processed/{id}.final_result", 
                       id=[extract_id_from_input(f) for f in glob.glob("my/path/*.txt")])

额外提示

如果你的规则链更长(比如b之后还有c、d规则),只需要基于checkpoint生成的文件列表,继续用同样的方式传递wildcard就行——核心就是让Snakemake在动态文件生成后,能重新识别到这些新的依赖关系。

内容的提问来源于stack exchange,提问作者Floris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:23:24