You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Snakemake使用Slurm模式时Python代码输出无法实时显示

问题描述

近期使用Snakemake时遇到输出同步问题:直接执行snakemake -c1运行调用spladder的规则时,Python代码中的print()输出能实时显示;但启用Slurm模式(snakemake -j1 --use-conda --slurm)后,这些Python输出要等任务结束或失败才会显示,而STAR等非Python程序的输出却能实时写入Slurm日志。相关规则代码如下:

rule spladder:
    input:
        genomes = [f"../ressources/genomes/{genome}/genomic.gtf" for genome in accessions['genome_id'].unique()],
        bams = [f"data/alignments/{rsa}/{rsa}_Aligned.sortedByCoord.out.bam" for rsa in accessions.index]
    output:
        [f"data/spladder/{genome}/merge_graphs_mutex_exons_C3.pickle" for genome in accessions['genome_id'].unique()] 
    threads: 20
    resources:
        mem_mb=1024*20, 
        runtime=60*8 
    run:
        print("========RUNNING JOB SPLADDER=========")
        print("\n\n\n")
        print(input.genomes)
        for genome in input.genomes:
            genome_id = re.search(r'genomes/(.+?)/', genome).group(1)
            filtered_accessions = accessions[accessions['genome_id'] == genome_id]
            rsa_ids = filtered_accessions.index.values
            if len(rsa_ids) > 0:
                bam_files = [f"data/alignments/{rsa}/{rsa}_Aligned.sortedByCoord.out.bam" for rsa in rsa_ids]
                bam_files = ",".join(bam_files)
                print(f"running spladder for {genome} with {bam_files}")
                cmd = fr"""
                mkdir -p data/spladder/{genome_id}

                spladder build --set-mm-tag nM --bams {bam_files} --annotation {genome} \
                --outdir data/spladder/{genome_id} --parallel {threads}
                """
                shell(cmd)
解决方案

问题根源是Python默认会缓冲标准输出(stdout),在Slurm的非交互式任务环境中不会自动实时刷新,而系统级工具(如STAR)通常采用行缓冲或无缓冲机制,因此能实时输出。以下是几种可行的解决方法:

1. 强制Python输出实时刷新

修改所有print()语句,添加flush=True参数,让Python立即刷新输出缓冲区:

print("========RUNNING JOB SPLADDER=========", flush=True)
print("\n\n\n", flush=True)
print(input.genomes, flush=True)
# 后续所有print都加上flush=True参数

也可以在run块开头全局设置无缓冲输出,后续print无需重复加参数:

run:
    import sys
    # 设置stdout为行缓冲模式,自动实时刷新
    sys.stdout = open(sys.stdout.fileno(), 'w', buffering=1)
    # 剩余代码不变

2. 利用Snakemake日志字段重定向输出

给规则添加log字段指定日志文件,将Python的stdout/stderr重定向到该文件,Slurm会实时同步文件内容:

rule spladder:
    input:
        genomes = [f"../ressources/genomes/{genome}/genomic.gtf" for genome in accessions['genome_id'].unique()],
        bams = [f"data/alignments/{rsa}/{rsa}_Aligned.sortedByCoord.out.bam" for rsa in accessions.index]
    output:
        [f"data/spladder/{genome}/merge_graphs_mutex_exons_C3.pickle" for genome in accessions['genome_id'].unique()] 
    threads: 20
    resources:
        mem_mb=1024*20, 
        runtime=60*8 
    log: "logs/spladder_{wildcards.genome_id}.log"  # 添加日志字段
    run:
        import sys
        # 重定向stdout和stderr到日志文件
        sys.stdout = sys.stderr = open(snakemake.log[0], 'w')
        # 后续所有print和shell命令输出都会写入日志文件,可实时查看
        print("========RUNNING JOB SPLADDER=========")
        # 剩余代码不变

3. 设置PYTHONUNBUFFERED环境变量

在调用Snakemake时添加环境变量,强制Python全程无缓冲输出:

PYTHONUNBUFFERED=1 snakemake -j1 --use-conda --slurm

也可以在规则中通过envvars字段全局设置:

rule spladder:
    # 其他字段不变
    envvars: ["PYTHONUNBUFFERED=1"]

内容的提问来源于stack exchange,提问作者Niklas E.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 00:12:37