Есть ли эквивалент 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"))