Rscript检测是否从另一个脚本调用/来源R脚本

时间:2017-12-21 20:25:14

标签: r shell unix rscript

我写了一个脚本,当它来源时检查脚本是否使用interactive()以交互方式运行。如果以交互方式运行,则不会搜索命令行参数。但是,如果它不是以交互方式运行,则会搜索命令行参数并引发错误。

这通常很好,但有时我会编写第二个R脚本,我想独立运行以处理一些数据。所以Script2源脚本1,Script1检测到它没有以交互方式运行,并开始搜索命令行参数并抛出错误。

除了interactive()之外,还有一种方法可以检测脚本的上下文吗?例如,我希望在直接运行时与在加载它以访问其内部函数之一时需要单独的行为。使用包我可以执行dplyr::arrange()之类的操作来访问arrange,而无需加载所有dplyr。

编辑:我当前的非常janky 解决方法是启动交互式会话,源脚本1,使用save.image()保存函数,然后在Script2中使用load来加载保存的.RData文件。但显然这不是......优雅。

我不认为我使用的确切代码是相关的,但包括它以防有人认为这对答案很重要......

剥离示例代码:

#!/usr/bin/env Rscript

library(optparse)

function1 <- function(etc,etc) {}
function2 <- function(etc,etc) {}

if(!interactive()) { 

    # example call
    # Rscript create_reference_file.R -c cd4cd8 -o /home/outputfolder/ 

    option_list = list(
        make_option(c('-c', '--cell'), type = 'character', default = NULL,
                    help = 'the name of the cell',
                    metavar = 'character'),
        make_option(c('-o','--outdir'), type = 'character', default = NULL, 
                    help = 'the location where you wish to store your output',
                    metavar = 'character'),
    )

    opt_parser <- OptionParser(option_list = option_list)
    opt <- parse_args(opt_parser)

    function1(opt); function2(opt) # etc etc, I do stuff with the opt inputs
}

1 个答案:

答案 0 :(得分:7)

修改

好的,这很像python的__name__技巧。 (以下答案,保留历史原因。)

function1 <- function(etc,etc) {}
function2 <- function(etc,etc) {}

if (sys.nframe() == 0L) {
    library(optparse)
    # ...
}

它与人们所希望的一样极简主义,不需要source脚本来了解它的任何内容,并且即使在嵌套时似乎也能正常工作。

通过查看每个Rscript: Determine path of the executing script的脚本名称,可以使用其他可能的机制(需要其他功能)。这里存在许多合理的(一些非常好的)解决方案,但它们都需要未在基础包中定义的预定义函数(或者要包含在要获取的脚本中的非平凡代码)。如果您希望&#34;假设已安装软件包X&#34;,则您的脚本可能变得不可移植。

(以前的答案,我建议你在上面使用。)

我会将其作为黑客攻击...它只比你的解决方法稍微少一点 janky ,但它依赖于 ing 脚本知道调用 ed 脚本正在测试的内容。

如果调用 ing 脚本设置变量:

BEING_SOURCED_FROM_SOMEWHERE <- TRUE

然后调用 ed 脚本可以检查它:

function1 <- function(etc,etc) {}
function2 <- function(etc,etc) {}

if (! exists("BEING_SOURCED_FROM_SOMEWHERE")) {
  library(optparse)
  # ...
}

我不喜欢它。它不像python的灵活性

if __name__ == "__main__":
    import optparse
    # ...

但我认为我不喜欢使用saveload进行函数定义。