第1章 Snakemake入门:简介、安装与核心概念

1.1 Snakemake是什么

Snakemake 是一个 Python 写的流程管理工具。说白了,它帮你把一串命令行工具串起来,自动处理依赖、并行和重复运行。

我最早接触它是在一个大项目里——要处理两百多个肿瘤样本的 WES 质控。用 Shell 脚本写了一套 pipiline,每次换参数都要手动改好几处,错了还不知道从哪断的。后来同事推荐 Snakemake,半天就把流程重写好了。嗯,从那以后我再也回不去纯 Shell 了。

它的核心思路很简单:

  • 每条分析步骤定义成一个 规则(rule)
  • 规则里写上输入文件、输出文件、要执行的命令
  • Snakemake 自动根据文件时间戳判断哪些需要重跑
  • 支持集群、云、多线程,一套代码到处跑
一句话总结: Snakemake 是「带依赖追踪的 Makefile」的现代化升级版,但专门为生物信息学场景优化过。

1.2 为什么生物信息学需要Snakemake

你想想看,生物信息学的日常工作是什么?fastp 质控、BWA 比对、samtools 排序、GATK 变异检测……每一步都依赖上一步的结果,中间还可能根据样本名生成不同文件。手动跑不仅容易忘,还容易把中间产物搞混。

Snakemake 正好解决这几个痛点:

痛点Snakemake 的解法
依赖混乱规则自动推导 DAG,不需要手动指定执行顺序
重复劳动通配符(wildcards)自动批量处理样本
断点续跑只重新运行因输入或参数改变的步骤
并行复杂内置多线程、集群提交、资源调度
可追溯差每个步骤的输入、输出、参数、版本都被记录
我习惯的做法: 把原始数据、参考基因组、每个样本的中间文件全部用 Snakemake 管理。这样即使半年后别人接手项目,看一眼 Snakefile 就知道所有步骤。换句话说,Snakemake 本身就是最好的文档。

1.3 安装Snakemake

安装方式有好几种。我个人最推荐用 Conda/Mamba,因为隔离环境好,依赖不会和系统打架。

方法一:通过 Conda 安装(推荐)

conda create -n snakemake_env -c conda-forge -c bioconda snakemake
conda activate snakemake_env

如果觉得 Conda 解析依赖太慢,换 Mamba:

conda install -c conda-forge mamba
mamba create -n snakemake_env -c conda-forge -c bioconda snakemake

方法二:通过 pip 安装

pip install snakemake

但要注意,系统里可能缺一些底层库(比如 graphviz 画图)。

验证安装

snakemake --version

输出类似 8.25.5 就是成功了。

我曾经遇到一个坑: 用 pip 安装后运行 snakemake --dag 报错说 graphviz 找不到。后来才发现系统没装 graphviz 的二进制包。Ubuntu 下需要先 sudo apt install graphviz。如果你是 Conda 装的,它会自带 graphviz,省心很多。

1.4 工作流基本概念:规则、输入、输出、通配符

Snakemake 的核心概念就四个,弄懂它们你就能写 80% 的流程了。

规则(rule)

每个规则定义一个分析步骤,包含名称、输入文件、输出文件和要运行的命令。

rule fastp_qc:
    input:
        "raw/{sample}_R1.fastq.gz",
        "raw/{sample}_R2.fastq.gz"
    output:
        "clean/{sample}_R1.clean.fastq.gz",
        "clean/{sample}_R2.clean.fastq.gz"
    shell:
        "fastp -i {input[0]} -I {input[1]} -o {output[0]} -O {output[1]}"

输入(input)与输出(output)

Snakemake 看输出文件的修改时间。如果输出文件不存在,或者比输入文件旧,就执行规则。否则跳过。你想想看,这个机制天然支持断点续跑。

通配符(wildcards)

上例里的 {sample} 就是通配符。Snakemake 自动把所有匹配的文件名提取出来,批量生成任务。比如说你 raw 目录下有 sampleA_R1.fastq.gz 和 sampleB_R1.fastq.gz,那么 {sample} 就会分别变成 sampleA 和 sampleB,每个样本独立跑一次。

核心逻辑: 通配符让一条规则覆盖所有样本,不需要写循环。

完整 Snakefile 最简结构:

# Snakefile
rule all:
    input:
        "clean/sample1_R1.clean.fastq.gz",
        "clean/sample2_R1.clean.fastq.gz"

rule fastp_qc:
    input:
        "raw/{sample}_R1.fastq.gz",
        "raw/{sample}_R2.fastq.gz"
    output:
        "clean/{sample}_R1.clean.fastq.gz",
        "clean/{sample}_R2.clean.fastq.gz"
    shell:
        "fastp -i {input[0]} -I {input[1]} -o {output[0]} -O {output[1]}"

运行:

snakemake -j 4

它会自动发现 raw 目录下所有匹配 {sample}_R1.fastq.gz 的文件,生成对应的 clean 输出。

1.5 核心概念的结构图

下面这张 SVG 图展示了一条 Snakemake 工作流的最小骨架。节点代表规则,箭头代表文件依赖。

Snakemake 工作流最小概念图 原始 FASTQ raw/{sample}_R*.fastq.gz fastp_qc 质控 + 过滤 clean FASTQ clean/{sample}_R*.clean.fastq.gz 通配符 {sample} 的作用 若 raw 目录中有 sampleA_R1.fastq.gz,sampleB_R1.fastq.gz 则 Snakemake 自动创建两个独立任务,分别处理 sampleA 和 sampleB → DAG(有向无环图) Snakemake 自动根据 input/output 构建 DAG, 保证每个规则执行前它的所有前置输出都已经就绪。

1.6 第一个Snakemake工作流实操体验

纸上得来终觉浅。咱们拿一个小例子跑一遍,帮你建立手感。

项目目录结构:

batch_qc_tutorial/
├── Snakefile
├── raw/
│   ├── sample1_R1.fastq.gz
│   ├── sample1_R2.fastq.gz
│   ├── sample2_R1.fastq.gz
│   └── sample2_R2.fastq.gz
└── clean/   (运行时自动创建)

Snakefile 内容:

rule all:
    input:
        expand("clean/{sample}_R1.clean.fastq.gz", sample=["sample1", "sample2"]),
        expand("clean/{sample}_R2.clean.fastq.gz", sample=["sample1", "sample2"])

rule fastp_qc:
    input:
        "raw/{sample}_R1.fastq.gz",
        "raw/{sample}_R2.fastq.gz"
    output:
        "clean/{sample}_R1.clean.fastq.gz",
        "clean/{sample}_R2.clean.fastq.gz"
    shell:
        "fastp -i {input[0]} -I {input[1]} -o {output[0]} -O {output[1]}"

运行命令:

cd batch_qc_tutorial
snakemake -j 2 --use-conda
注意: --use-conda 参数让 Snakemake 自动为每个规则创建 Conda 环境(如果你在规则里写了 conda: 指令)。对于简单的本地调试,可以不加。

执行后你会在终端看到类似输出:

Building DAG of jobs...
Job stats:
job                    count    min threads    max threads
---------------  ----------  -------------  -------------
all                         1              1              1
fastp_qc                    2              1              1
total                       3              1              1

[Fri Dec 16 10:30:05 2025]
rule fastp_qc:
    input: raw/sample1_R1.fastq.gz, raw/sample1_R2.fastq.gz
    output: clean/sample1_R1.clean.fastq.gz, clean/sample1_R2.clean.fastq.gz
    jobid: 1
    wildcards: sample=sample1
    ...

看到 Building DAG of jobs... 就说明 Snakemake 已经在工作了。结束后去 clean 目录看看,两个样本的质控结果已经躺好了。

个人建议: 第一次运行之前先用 snakemake -n 做 dry-run,它会打印所有要执行的任务,但不会真的跑。这步能帮你提前发现拼写错误或路径问题,省得中途翻车。

如果你在实验环境里没有 fastp 命令,可以按下面的方式改用简单的 echo 模拟一下:

rule fastp_qc:
    input:
        "raw/{sample}_R1.fastq.gz"
    output:
        "clean/{sample}_R1.clean.fastq.gz"
    shell:
        "echo 'Pretend to process {input} -> {output}'"

这样虽然不会真的生成文件,但足够让你理解规则是怎么触发的。嗯,先跑通再上真工具,是我一贯的调试策略。