首页 > 解决方案 > 在不定义绝对路径的情况下访问外部蛇形目录中的脚本

问题描述

我的最终目标是在 GitHub 存储库上托管一个 snakemake 工作流程,可以作为一个 snakemake 模块访问。我在托管它之前在本地进行测试,但我遇到了一个问题。我无法访问snakemake 模块目录中的脚本。它在当前的 snakemake 目录中本地查找脚本,如果我的最终目标是远程托管模块,我显然无法在本地移动。

在远程目录中访问 Conda 环境时,我没有看到这个问题。有没有办法模仿脚本目录的这种行为?如果可以将其应用于访问远程脚本目录,我将对绝对路径引用开放。这是一个重现错误的虚拟示例:

Snakemake 版本:6.0.5

树结构:

.
├── external_module
│   ├── scripts
│   │   ├── argparse
│   │   └── print.py
│   └── Snakefile
└── Snakefile

本地蛇文件:

module remote_module:
    snakefile: "external_module/Snakefile"

use rule * from remote_module

use rule foo from remote_module with:
    input:
        "complete.txt"

外部蛇文件:

rule foo:
    input:
        "complete.txt"

rule bar:
    output:
        touch(temp("complete.txt"))
    shell:
        "scripts/print.py -i foo"

打印.py

import argparse

def get_parser():
    parser = argparse.ArgumentParser(
        description='dummy snakemake function',
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    parser.add_argument("-i", default=None,
                        help="item to be printed")
    
    return parser

def main():
    args = get_parser().parse_args()
    print(args.i)

if __name__ == '__main__':
    main()

Snakemake管道执行

(base) bobby@SongBird:~/remote_snakemake_test$ snakemake --cores 4
Building DAG of jobs...
Using shell: /usr/bin/bash
Provided cores: 4
Rules claiming more threads will be scaled down.
Job counts:
        count   jobs
        1       bar
        1       foo
        2

[Fri Mar 26 10:12:50 2021]
rule bar:
    output: complete.txt
    jobid: 1

/usr/bin/bash: scripts/print.py: No such file or directory
[Fri Mar 26 10:12:50 2021]
Error in rule bar:
    jobid: 1
    output: complete.txt
    shell:
        scripts/print.py -i foo
        (one of the commands exited with non-zero exit code; note that snakemake uses bash strict mode!)

Shutting down, this might take some time.
Exiting because a job execution failed. Look above for error message
Complete log: /home/bobby/remote_snakemake_test/.snakemake/log/2021-03-26T101250.118440.snakemake.log

任何见解将不胜感激。谢谢!

标签: snakemake

解决方案


模块对我来说是新的,所以这可能不是最好的方法。该行为似乎有点错误,但这目前有效......

看起来您可以访问工作流的基本目录., withworkflow.basedir和外部目录external_module, with workflow.current_basedirinside external_module/Snakefile。但是,在模块中执行规则时,您似乎无法在规则中使用这些功能。如果将其保存为变量,则以后可以使用它,但前提是该变量也在主 Snakefile 中定义。

这有效:

# Snakefile
module remote_module:
    snakefile: "external_module/Snakefile"

use rule * from remote_module

my_basedir = "DOESN'T MATTER"
use rule foo from remote_module with:
    input:
        "complete.txt"

# external_module/Snakefile
my_basedir = workflow.current_basedir

rule foo:
    input:
        "complete.txt"

rule bar:
    output:
        touch(temp("complete.txt"))
    shell:
        "{my_basedir}/scripts/print.py -i foo"

my_basedir将具有正确目录的值。但是,如果您删除my_basedir顶层 Snakefile 中的赋值,则该变量将不可用,但显然该值本身并未被使用。看起来像一个最终会被修补的错误,所以将它设置为workflow.basedir + '/external_module'.

我还要注意,如果您在不同的工作目录中运行工作流,则 print.py 的相对路径将在原始示例中中断。将该路径设置为配置变量并在主 Snakefile 中正确设置它可能更安全、更理智,如下所示:

# Snakefile
config['my_basedir'] = workflow.current_basedir + '/external_module'
module remote_module:
    snakefile: "external_module/Snakefile"

use rule * from remote_module

use rule foo from remote_module with:
    input:
        "complete.txt"

# external_module/Snakefile
rule foo:
    input:
        "complete.txt"

rule bar:
    output:
        touch(temp("complete.txt"))
    shell:
        "{config[my_basedir]}/scripts/print.py -i foo"

感谢您提供的好玩具示例!


推荐阅读