3、工作流运行控制:本地运行、Dry-run、强制重新运行

Snakemake 跑起来其实就一行命令。但很多新手上来就 snakemake 回车,结果跑了一半发现规则写错、输入文件路径不对,或者某个步骤需要重跑……浪费时间不说,还容易把中间产物搞乱。

我个人习惯是:无论工作流多简单,都先用 dry-run 看一眼执行计划,再用 --force 精确控制重跑范围。这三个模式——本地运行、Dry-run、强制重新运行——就是日常调工作流最常用的三板斧。

3.1 本地运行:最直接的启动方式

Snakemake 默认就是本地执行。你在终端敲 snakemake,它会根据 Snakefile 的依赖关系,按顺序或并行(如果你指定了 -j)运行所有规则。

# 简单启动,用 4 个 CPU 核心并行
snakemake -j 4

这里 -j 后面的数字是同时运行的任务数。我遇到过的小坑:特征工程的数据量一大,-j 设太高内存吃紧。建议先 -j 2 试跑一次。

小提示: 本地运行时 Snakemake 会在当前目录下生成 .snakemake 隐藏文件夹,里面存了 lock 文件和日志。如果工作流意外中断,记得先 snakemake --unlock 再重启。

本地运行适合小数据量、快速调试的场景。我在做特征工程原型时,往往先用本地模式调通几条测试数据,再换集群跑全量。

3.2 Dry-run:先看看,不动手

说白了就是“模拟执行”。加个 -n(或 --dry-run)参数,Snakemake 会打印出所有要执行的规则和输入输出文件,但实际什么都不跑。

snakemake -n -j 4

输出大概长这样:

Building DAG of jobs...
Job stats:
job                      count    min files    max files    ...
------------------------ ------  ----------  ----------
generate_features            1           1            1
select_features              1           1            1
train_model                  1           1            1
total                        3           3            3

This was a dry-run (flag -n). The actual command would have produced the output files.
...

你会发现它构建了一个 DAG(有向无环图),告诉你每个规则的执行顺序。我曾经在一次特征筛选实验中,因为过滤条件的输入文件写反了,干跑发现规则间有循环依赖,还好 dry-run 提前报错,没浪费两小时计算资源。

注意事项: Dry-run 不会检查输入文件是否存在,也不会校验输出文件是否可写。它只验证规则间的依赖逻辑。如果你要检查文件路径是否配齐,可以加 --detailed-summary 参数。

3.3 强制重新运行:精确控制重跑范围

工作流的产物一旦生成,Snakemake 会认为它是“最新的”,再次执行会跳过相应规则。但有时候我们需要强制重新跑某个步骤——比如特征工程的预处理逻辑改了,或者数据源更新了。这时候 --force 系列参数就派上用场了。

参数作用典型场景
--force (或 -f)强制重新运行指定规则只想重跑单个 step,比如 snakemake -f normalize
--forcerun (或 -R)强制重新运行目标规则及其上游修改了某个下游规则后,连带重跑所有依赖它的规则
--forceall (或 -F)忽略所有已有输出,重新跑整个工作流换了新数据源,或彻底重构了 Snakemake 规则

举个例子,假设特征生成规则叫 generate_features,输出文件 features.parquet 已经存在。你想更新它的参数后重跑:

snakemake -f generate_features -j 4

如果下游的筛选规则也依赖这个新特征,而且你想确保它们都重算一遍,用 -R:

snakemake -R generate_features -j 4

它会找到所有以 generate_features 为上游的规则,一起强制重跑。

避坑指南: 我曾经不小心在 `--forceall` 模式下跑了一个半月才搞定的超大规模特征工程……结果所有中间文件被删掉重来,白白浪费3天。建议优先用 `-f` 指定具体规则,别因为省事就上 `-F`。

三种运行模式的关系

这三种模式并非对立——它们常常组合使用。比如我先 dry-run 看计划,再用 -f 精准修改某个步骤,最后本地跑。下图直观展示了它们之间的切换逻辑:

Snakemake 运行模式决策流程 用户执行 snakemake Dry-run(-n) 只打印执行计划 本地运行(默认) 按依赖执行,跳过已有输出 强制重跑(-f / -R / -F) 忽略已有产物,重新执行 工作流执行 / 输出结果 修改规则后重跑 经验之谈 先 dry-run → 再局部 force → 最后跑全量。这个顺序让我少踩了无数坑。

你想想看,有了这三招,几乎能应付所有常见场景:

  • 新写 Snakefile → 先用 -n 验证逻辑
  • 改了一个规则 → 用 -f 只重跑它
  • 所有规则都变更了 → 用 -F 彻底重新来

组合使用示例

我在实际项目中,经常先 dry-run 看整个调度计划对不对,然后用 -f 修正个别出错步骤。比如:

# 1. 先看计划
snakemake -n -j 4

# 2. 发现特征选择步骤需要重跑(因为改了参数)
snakemake -f select_features -j 4

# 3. 跑完后确认结果,再用本地模式完成剩余步骤
snakemake -j 4
注意: 如果工作流因为权限或锁文件卡住,先执行 snakemake --unlock 清理锁,否则直接敲任何参数都没用。这是我最开始踩的坑——一上午都在想为什么命令不生效,结果发现忘了 unlock。

嗯,这三种运行控制方式,算是 Snakemake 日常使用的基石。不管是特征工程的小流程,还是跨集群的大 pipeline,理解它们再动手,效率能翻倍。