第三章:第一个Snakemake流程:编写简单的Snakefile,运行流程
说实话,很多教程上来就甩一堆规则、通配符、配置,看得人头皮发麻。我个人习惯是先跑起来一个最小例子,亲眼看到输出文件生成,心里再踏实。这一章我们就干一件事——写一个最简单的Snakefile,然后敲命令让它跑通。
3.1 准备工作:文件和目录结构
先搭个基础环境。你随便找个空目录,比如my_first_flow,在里面放一个输入文件input.txt,内容就写几行文本:
hello world
snakemake is fun
let us start
然后在这个目录里再新建一个空文件,命名为Snakefile——注意首字母大写,没有后缀。Snakemake默认就找这个名字的文件。
小习惯: 我每建一个新项目都会先写好
Snakefile和README.md,哪怕规则为空,因为后面加东西时大脑负担小。
3.2 编写你的第一个Snakefile
在Snakefile里写入下面内容。别复制粘贴,最好手打一遍,感受一下语法:
rule sort_lines:
input:
"input.txt"
output:
"output.txt"
shell:
"sort {input} > {output}"
我们来拆解一下这个规则(rule):
sort_lines是这个规则的名字,随你起,但最好有意义。我在项目中见过有人直接写rule one,维护时根本不知道它在干啥。input:指定输入文件,这里就是input.txt。output:指定输出文件,Snakemake会用这个文件名来追踪是否已生成。shell:告诉Snakemake执行哪条shell命令。注意花括号{input}和{output}会被自动替换成实际文件名。
关键一件事: output是触发流程的钥匙。Snakemake只会生成你在命令行里要求的目标文件,然后反向推导需要执行哪些规则。
3.3 运行流程
现在打开终端,进入你的项目目录,执行:
snakemake -c1 output.txt
-c1表示使用1个CPU核心。第一次运行你会看到类似这样的输出:
Building DAG of jobs...
Using shell: /bin/bash
Provided cores: 1
Rules claiming more threads will be scaled down.
Job stats:
job count min threads max threads
-------- ----- ----------- -----------
sort_lines 1 1 1
[Wed Jan 24 10:15:22 2024]
rule sort_lines:
input: input.txt
output: output.txt
jobid: 0
reason: Missing output files: output.txt
resources: tmpdir=/tmp
sort input.txt > output.txt
运行结束后,看看目录:多了一个output.txt。打开它,发现内容已经被按字母排序了。嗯,就是这么简单。
曾经有个坑: 我记得第一次用Snakemake时直接把输出文件写成
output.txt,然后第二次运行时报错“文件已存在”。Snakemake默认不允许覆盖已有输出。你要么删除文件重新跑,要么加--force参数。后来我就养成了每次实验前先snakemake --delete-all-output清干净的习惯。
3.4 理解Snakemake干了什么
你可能觉得这不就是一行sort命令吗?直接敲也能做。但你想想看,如果后面有上百个文件,每个都要先排序再压缩再比对……手工逐个执行会疯掉的。Snakemake的价值在于它帮你自动构建依赖图。
下面这张图展示了一个完整的工作流周期——从你编写Snakefile到获得最终输出,Snakemake帮你省掉了大量体力活:
你看,Snakemake替你完成了最繁琐的两步:① 当多个规则串联时,自动解析依赖关系,决定谁先执行;② 检查输出文件是否已经存在,避免重复劳动。
3.5 核心语法速查
下面这个表格是我在带团队时经常贴在白板上的,初学阶段记住这四个关键字就够了:
| 关键字 | 作用 | 是否必须 |
|---|---|---|
rule |
定义一个规则,后面跟规则名(如 sort_lines) |
是 |
input |
指定该规则需要的输入文件(可多个) | 否,但一般会用 |
output |
指定该规则产生的输出文件 | 是(除非用 nooutput) |
shell |
写入要在 shell 中执行的命令,用 { } 引用 input/output |
是(或改用 run) |
一个实用技巧: 如果你不确定某个规则会不会跑,先用
我在大项目里几乎每次提交代码前都会先 dryrun 一遍,确认逻辑没断。
snakemake --dryrun 目标文件。它只会打印出计划执行的命令而不真正运行,非常安全。我在大项目里几乎每次提交代码前都会先 dryrun 一遍,确认逻辑没断。
3.6 避坑指南:你很可能遇到的三个问题
- 输出现成文件被杀:再次运行相同的
snakemake output.txt会提示“Nothing to be done”。想重新跑?加-f或--force,或者删掉输出文件。 - 命令写错没提示:Snakemake 本身不校验 shell 命令是否正确,它只管执行。如果输出了错误日志,它也不会自动终止(除非设置
wms_monitor)。我习惯在 shell 命令最后加&& echo "done"来辅助调试。 - 路径问题:Snakemake 默认以当前工作目录执行 shell 命令。如果输入文件在子目录,一定要写相对路径,比如
"data/input.txt",否则会报 FileNotFoundError。