【问题标题】:Rscript detect if R script is being called/sourced from another scriptRscript 检测是否从另一个脚本调用/获取 R 脚本
【发布时间】:2018-06-04 13:27:42
【问题描述】:

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

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

除了interactive() 之外还有什么方法可以让脚本检测其上下文吗?例如,当它直接运行时与加载它以访问其内部功能之一时,我想要单独的行为。使用软件包,我可以执行类似dplyr::arrange() 的操作来访问arrange,而无需加载所有dplyr。

编辑:我目前非常麻烦的解决方法是启动交互式会话,源 Script1,使用 save.image() 保存函数,然后在 Script2 中使用 load 加载保存的 . R 数据文件。但这显然不是……优雅。


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

精简示例代码:

#!/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
}

【问题讨论】:

  • 您正在寻找类似于 python 的if __name__ == '__main__': 的东西,对吧?
  • (如果你不会说 python,这里有一些关于该参考的背景:stackoverflow.com/questions/419163/what-does-if-name-main-do
  • 是的!这基本上与我正在寻找的功能相同(或可以实现类似结果的功能)。

标签: r shell unix rscript


【解决方案1】:

编辑

好的,这更像是 python 的 __name__ 技巧。 (以下之前的答案,出于历史原因保留。)

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

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

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

根据Rscript: Determine path of the executing script,可以通过查看脚本名称来使用其他可能的机制(需要额外的功能)。那里存在许多看似合理(一些非常好的)的解决方案,但它们都需要一个未在基本包中定义的预定义函数(或包含在要获取的脚本中的非平凡代码)。如果你想“假设包 X 已安装”,那么你的脚本可能变得不可移植。


(上一个答案,我建议你用上面的。)

我将把它作为一个 hack 扔掉......它只比你的解决方法略少janky,但它依赖于调用ing 脚本知道什么called 脚本正在测试。

如果调用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 来定义函数。

【讨论】:

  • 顺便说一句:随意让您的原始问题 stew 看看其他人是否有更优雅的解决方案。如果您过早接受它,其他回答者甚至可能会放弃阅读该问题。 :-)
  • 也许@DirkEddelbuettel 在littler 实用程序中有一些东西?
  • 这并不完美,但与我之前的尝试相比,这绝对是朝着正确方向迈出的一大步。
  • @Brandon,我认为我的编辑包括您正在寻找的优雅解决方案。
  • 小想法:为了后来者的利益,请编辑您的答案,以便您使用 sys.nframe 进行简约优雅的编辑...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-15
  • 2019-06-18
  • 1970-01-01
  • 1970-01-01
  • 2011-06-01
  • 2022-08-02
  • 2016-06-12
相关资源
最近更新 更多