Snakemake含时间戳输出文件报错求助:文件创建两次导致文件名不匹配
Snakemake含时间戳输出文件报错求助:文件创建两次导致文件名不匹配
嗨,我帮你拆解下这个问题的核心原因,再给你几个靠谱的解决办法~
问题根源:Snakefile会被多次解析执行
你遇到的报错本质是Snakemake的运行机制导致全局代码重复执行:
- 第一次是启动Snakemake时,它会加载整个Snakefile来构建依赖关系图(DAG),这时候你写在全局的时间戳生成代码会执行一次,确定
rule all和rule main_rule期望的输出文件名; - 第二次是实际执行
main_rule的时候(尤其是在HPC集群环境下,每个任务可能会在独立的进程或节点中启动),Snakefile会被重新加载,全局代码再次运行,生成一个新的时间戳——这时候实际创建的是新时间戳的文件,但Snakemake还在找第一次生成的旧文件名,自然就触发了MissingOutputException。
而你在Windows本地运行正常,是因为本地是单进程执行,Snakefile只被加载了一次,时间戳全程保持一致。
解决方案:让时间戳只生成一次
这里有两种简单且可靠的解决思路:
方案1:全局一次性确定时间戳
利用Python模块加载的特性——全局代码只会在模块第一次被导入时执行一次,后续所有规则都复用这个固定的时间戳:
#!/bin/python print('import packages') from datetime import datetime import time # 模块加载时计算一次,后续全程不变 now = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") tarfile = now + '_stardist.tar' print(tarfile) rule all: input: tarfile rule main_rule: output: tarfile shell: "touch {output}"
(也可以保留原来的run:写法,核心是让tarfile成为预先确定的固定值)
方案2:通过命令行传递时间戳
如果想让时间戳严格等于启动Snakemake的时刻,而非脚本加载时刻,可以用--config参数传递:
启动命令:
snakemake -s snakefile --cores 1 --config timestamp=$(date +%Y-%m-%d_%H-%M-%S)
对应的Snakefile:
#!/bin/python print('import packages') rule all: input: f"{config['timestamp']}_stardist.tar" rule main_rule: output: f"{config['timestamp']}_stardist.tar" shell: "touch {output}"
这种方式下,时间戳完全由启动命令决定,不管Snakefile被加载多少次,都用同一个值。
验证效果
修改后再运行脚本,你会发现import packages和时间戳只会打印一次,DAG构建和任务执行用的是同一个文件名,就不会出现文件找不到的问题了。
备注:内容来源于stack exchange,提问作者Antje Janosch
相关产品推荐
相关产品推荐

