Snakemake checkpoint生成未知文件后单文件并行处理报错问题
问题根源
报错来自两个逻辑错误:
glob_wildcards返回的是包含匹配结果的命名元组,没有提取通配符i对应的实际值列表,直接把整个元组对象传给了expand,导致通配符解析时拿到的是整个对象的字符串表示,也就是报错里的['1', '2', '3']- 不需要依赖聚合规则来触发单文件处理流程,只要把最终要生成的所有单文件处理结果作为
rule all的输入,Snakemake会自动在checkpoint执行完成后,为每个匹配到的文件生成独立的并行处理任务,不需要额外的中间聚合逻辑。
修正要点
- 调用
glob_wildcards后必须通过.通配符名的方式提取匹配到的值列表,不能直接把返回的命名元组传入expand - 把动态解析文件列表的函数直接绑定到
rule all的输入上,目标直接指向每个文件处理后的输出路径,Snakemake会自动推导所有需要执行的单文件处理任务,无需强制通过聚合规则触发 - 目录创建的shell命令加
-p参数,避免目录已存在时执行报错
修正后可运行代码
from os.path import join # checkpoint执行完成后,动态扫描所有生成的gz文件,返回对应解压后txt文件的路径列表 def get_all_gunzip_output(wildcards): ckpt_dir = checkpoints.create_gzip_file.get(**wildcards).output[0] # 提取匹配到的所有i通配符的值 file_ids = glob_wildcards(join(ckpt_dir, "{i}.txt.gz")).i return expand(join(ckpt_dir, "{i}.txt"), i=file_ids) rule all: input: get_all_gunzip_output, checkpoint create_gzip_file: output: directory("my_directory/"), shell: """ mkdir -p my_directory/ cd my_directory for i in 1 2 3; do gzip < /dev/null > $i.txt.gz; done """ rule gunzip_file: input: join("my_directory", "{i}.txt.gz"), output: join("my_directory", "{i}.txt"), shell: """ gunzip -c {input} > {output} """ # 若后续需要聚合所有解压后的文件,取消下方注释即可,不需要时可直接删除 # rule aggregate: # input: # get_all_gunzip_output, # output: # "aggregated.txt", # shell: # "cat {input} > {output}"
执行效果
- Snakemake会首先执行
create_gzip_filecheckpoint,生成目标目录及未知数量的gz文件 - checkpoint执行完成后自动重新解析DAG,扫描目录下所有匹配的gz文件,为每个文件生成独立的
gunzip_file任务,按设置的核心数自动并行执行 - 每个任务的
{i}通配符会正确匹配单个文件的编号,不会再出现通配符被解析为列表的错误
内容的提问来源于stack exchange,提问作者hermidalc
相关产品推荐
相关产品推荐

