Есть ли эквивалент R для Python "if __name__ == "__main__": main()"?

Задача состоит в том, чтобы получить два простых способа получить некоторый код, скажем, func.R, содержащий функцию. призвание R CMD BATCH func.R инициализирует функцию и оценивает В течение сеанса выдачи source("func.R") просто инициализирует функцию. Любая идея?

6 ответов

Решение

Я думаю, что interactive() функция может работать.

Эта функция возвращает TRUE когда R используется в интерактивном режиме и FALSE иначе. Так что просто используйте if (interactive())

то есть эквивалент

if (!interactive()) {
  main()
}

Другой вариант:

#!/usr/bin/Rscript

# runs only when script is run by itself
if (sys.nframe() == 0){
# ... do main stuff
}

Вы можете передать аргументы в R, и, если аргумент присутствует, запустить main(). Более подробно об аргументах здесь: http://yangfeng.wordpress.com/2009/09/03/including-arguments-in-r-cmd-batch-mode/

Это большая работа, но я наконец-то ее получил (и разместил в Rosetta Code).

В этом примере экспортируется функция с именем meaningOfLife, Когда скрипт запускается сам по себе, он запускается main, При импорте другим R-файлом он не запускается main,

#!/usr/bin/Rscript

meaningOfLife <- function() {
    42
}

main <- function(program, args) {
    cat("Main: The meaning of life is", meaningOfLife(), "\n")
}

getProgram <- function(args) {
    sub("--file=", "", args[grep("--file=", args)])
}

args <- commandArgs(trailingOnly = FALSE)
program <- getProgram(args)

if (length(program) > 0 && length(grep("scriptedmain", program)) > 0) {
    main(program, args)
    q("no")
}

Я задал похожий вопрос, в ответ Мэтью Плурд предложил использовать getOption('run.main', default=TRUE) в основном сценарии, а затем настройки options(run.main=FALSE) перед звонком source(), Это сработало в моем случае.

В противном случае более простой шаблон, когда у вас есть сценарий R, создающий несколько функций, и вы хотите написать несколько строк в конце сценария, чтобы поэкспериментировать с использованием функции: поместите эти дополнительные строки в if(FALSE){} блок.

Это работает довольно хорошо для моего использования. Если у вас есть два файла и вы хотите использовать один с другим, запуская только определенную часть файла.

родительский файл: parent.R

      print("Running Parent File")
`__name__` <- "__main__"
print(paste0("This file is : ", `__name__`))

`__src__` <- "__not.main__"
source("child.R")
rm(`__src__`)

дочерний файл: child.R

      print("Running Child File")
`__name__` <- "__main__"
if (exists("__src__")){`__name__` <- `__src__`}

if (`__name__` == "__main__"){
  print(paste0("This file is : ", `__name__`))
} else {
  print(paste0("This file is : ", `__name__`))
}

Вывод при запуске Rscript parent.R

      [1] "Running Parent File"
[1] "This file is : __main__"
[1] "Running Child File"
[1] "This file is : __not.main__"

Вывод при запуске Rscript child.R

      [1] "Running Child File"
[1] "This file is : __main__"

Более надежным методом было бы написать пользовательскую исходную функцию, в которую можно включить список аргументов.

      source2 <- function(file, args = list()){
    
  tryCatch(
    expr = {
      assign("__src__", "__not.main__", envir = globalenv())
      assign("__src.args__", args, envir = globalenv())
      source(file)
    },
    error = function(e){
      message("File could not be sourced")
    },
    finally = {
      rm(list = c("__src__", "__src.args__"), envir = globalenv());
      assign("__name__", "__main__", envir = globalenv())
    })
}

source2("child.R", args = list("list", "of", "arguments"))
Другие вопросы по тегам