为何小于100KB的输入文件被touch后Snakemake不重跑工作流?
版本信息
Snakemake版本:8.16.0
Snakefile内容
rule test: input: "input.txt" output: "output.txt" shell: """ cat {input} > {output} """
input.txt的大小小于100,000字节(例如99,999字节)
操作流程
- 首次执行
snakemake -c1,一切正常,生成output.txt。 - 执行
touch input.txt修改文件时间戳。 - 再次执行
snakemake -c1,Snakemake提示Nothing to be done (all requested files are present and up to date).(不符合预期)。 - 向
input.txt添加字符,使其大小达到或超过100,000字节。 - 执行
snakemake -c1,rule test会重新运行,因为输入文件已变更。 - 再次执行
touch input.txt(同步骤2)。 - 执行
snakemake -c1,rule test会重新运行,因为输入文件修改日期已变更。
问题
为何当输入文件大小小于100,000字节时,执行touch后Snakemake不重跑工作流?如何让Snakemake在touch任意输入文件时都重跑?
已在两台设备上测试,结果一致。
原因解释
Snakemake默认采用差异化的文件变更检测策略:
- 对于小于100KB(100,000字节)的文件,它会计算文件内容的哈希值(checksum)判断变化。
touch仅修改时间戳,未改变文件内容,哈希值不变,因此Snakemake判定文件未更新,不会重跑规则。 - 对于大于等于100KB的文件,出于性能优化,Snakemake改用文件修改时间(mtime)和大小判断变更。
touch修改了mtime,触发Snakemake判定文件已更新,因此会重跑规则。
解决办法
有两种方式可实现touch任意输入文件时都触发重跑:
- 全局强制使用修改时间检测
执行Snakemake时添加--cache-mtime参数,强制所有文件基于修改时间和大小判断变更:
snakemake -c1 --cache-mtime
- 针对单个规则指定检测方式
在规则中通过cache参数,指定该规则的输入文件使用修改时间检测:
rule test: input: cache("input.txt") output: "output.txt" shell: """ cat {input} > {output} """
如果有多个输入文件,也可以逐个标记:
rule test: input: "file1.txt", cache("file2.txt") # ...其余规则内容
内容的提问来源于stack exchange,提问作者ManJi
相关产品推荐
相关产品推荐

