Snakemake 工作流入门:安装、语法与第一个 Snakefile
好,咱们正式开始动手了。这一章,我带你从零搭建 Snakemake 环境,并写出第一个能跑的工作流。说实话,Snakemake 的语法非常直观,你只要理解了一个核心逻辑——规则(rule)就是一个小任务——剩下的全是细节。
2.1 安装 Snakemake:两种方式,我推荐第二种
安装这件事,不同人有不同习惯。我个人偏好 conda/mamba 来管理环境,因为后面做 ADMET 预处理时,依赖的第三方工具(比如 OpenBabel、RDKit)版本冲突真的让人头大。
方式一:pip 直接安装
pip install snakemake
这种方式最快,但我踩过坑:如果系统里已经装了其他 bioinfo 工具,pip 可能会把依赖搞乱。适合你只是想快速试试语法的场景。
方式二:conda/mamba 创建干净环境(我推荐)
conda create -n snakemake_env -c conda-forge -c bioconda snakemake
conda activate snakemake_env
或者用 mamba(更快):
mamba create -n snakemake_env snakemake
mamba activate snakemake_env
验证安装
安装完后,在终端跑一下这个命令:
snakemake --version
如果看到类似 7.32.4 的版本号,那就成了。
2.2 Snakefile 的核心语法:规则(Rule)
Snakemake 的构建块就是 规则。一个规则定义了三样东西:输入(input)、输出(output) 和 要运行的命令(shell 或 run)。
你看,这就是一个最简规则:
rule say_hello:
output:
"hello.txt"
shell:
"echo 'Hello, Snakemake!' > {output}"
这里面有几个关键点:
- rule 名字(这里是
say_hello)就像给任务起的标签,不能重复。 - output 定义了规则会生成什么文件。
- shell 里写的命令会被 Snakemake 执行,
{output}会自动替换成输出文件的路径。
说白了,Snakemake 就是根据文件的存在与否来决定要不要跑某个规则。如果 hello.txt 已经存在,它就会跳过。
2.3 第一个 Snakefile:从零到一
好,咱们写个真正能跑的。假设我们要从 raw_data.smi 这个 SMILES 文件,通过 OpenBabel 转换成 mol2 格式。我们把这个工作流写进 Snakefile:
rule convert_to_mol2:
input:
"data/raw_data.smi"
output:
"data/processed/raw_data.mol2"
shell:
"obabel {input} -O {output} --gen3D"
在终端里,cd 到 Snakefile 所在目录,然后执行:
snakemake -j 1
-j 1 表示用 1 个 CPU 核心来跑。如果一切顺利,你会在 data/processed/ 下看到生成的 mol2 文件。
data/processed/ 目录。Snakemake 默认不会自动创建输出目录,你得手动建,或者用 directory() 指令。记得提前 mkdir -p data/processed。
2.4 Snakemake 的基本概念:规则、目标和执行
为了让理解更扎实,我把 Snakemake 的核心元素整理成了一张表:
| 概念 | 说明 | 示例 |
|---|---|---|
| 规则 (rule) | 定义一个任务单元 | rule convert: ... |
| 输入 (input) | 该规则依赖的文件 | input: "raw.smi" |
| 输出 (output) | 该规则要生成的文件 | output: "processed.mol2" |
| shell 命令 | 实际运行的命令行 | shell: "obabel {input} -O {output}" |
| 目标 (target) | Snakemake 决定先构建哪个文件 | 默认第一个规则的输出 |
| 执行 (execution) | Snakemake 自动推导依赖关系并运行 | snakemake -j 4 |
你想想看,Snakemake 本质上就是一个智能调度器。你告诉它想要什么文件,它自己会去找需要的输入文件在哪里,按顺序执行规则。我最初用的时候觉得最神奇的是,如果中间某一步的输入文件没生成,它不会傻等,而是直接报错告诉你“少了啥”。
2.5 多规则工作流:搭建简单处理链
实际项目中,很少只有一个规则。比如 ADMET 预处理常常需要:读取 SMILES → 生成 3D 结构 → 计算分子描述符。我们写个三步骤的工作流:
rule generate_3d:
input:
"data/mol.smi"
output:
"data/mol_3d.sdf"
shell:
"obabel {input} -O {output} --gen3D"
rule calculate_descriptors:
input:
"data/mol_3d.sdf"
output:
"data/descriptors.csv"
shell:
"obabel {input} -O {output} --append descriptors"
当你执行:
snakemake -j 1
Snakemake 会做以下事情:
- 发现
calculate_descriptors需要data/mol_3d.sdf。 - 检查这个文件是否存在——不存在,于是去找生成它的规则
generate_3d。 - 按顺序依次执行。
output 放在最前面。否则,可以用 snakemake data/descriptors.csv 来指定目标文件。
2.6 本章核心流程:Snakemake 工作流逻辑图
我把刚才讲的核心逻辑——输入 → 规则执行 → 输出 → 依赖追踪——画成了一张图,方便你直观理解:
2.7 常见错误与调试技巧
我在第一次带学生搭建 Snakemake 环境时,大家犯的错误基本集中在这几个地方:
- 路径不对:Snakemake 的工作目录是运行命令的目录,不是 Snakefile 所在的目录。我建议用绝对路径或基于项目根目录的相对路径。
- 输出文件格式不匹配:比如你在
shell里用obabel生成.sdf,但output写的是.xyz,Snakemake 不会检查内容格式——它只认文件名。我就遇到过生成了错误格式然后下游报错,排查了好久才发现是名字写错了。 - 忘记激活 conda 环境:Snakemake 本身可以激活 conda 环境,但如果你直接裸跑命令,系统会找全局的
obabel。很多人因此莫名其妙的报“command not found”。
conda: "env.yaml" 来指定每个规则的环境。但我个人建议前期先保持简单,用一个全局环境跑通再说。