Is there an R equivalent of the pythonic "if __name__ == "__main__": main()"?

PythonR

Python Problem Overview


The objective is to have two simple ways to source some code, say func.R, containing a function. Calling R CMD BATCH func.R initializes the function and evaluates is. Within a session, issuing source("func.R") simply initializes the function. Any idea?

Python Solutions


Solution 1 - Python

I think that the interactive() function might work.

This function returns TRUE when R is being used interactively and FALSE otherwise. So just use if (interactive())

i.e. the equivalent is

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

Solution 2 - Python

Another option is:

#!/usr/bin/Rscript

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

Solution 3 - Python

You could pass arguments into R, and if an argument is present run main(). More on arguments here: http://yangfeng.wordpress.com/2009/09/03/including-arguments-in-r-cmd-batch-mode/

Solution 4 - Python

It's a lot of work, but I finally got it (and posted at Rosetta Code).

This example exports a function called meaningOfLife. When the script is run by itself, it runs main. When imported by another R file, it does not run 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")
}

Solution 5 - Python

I asked a similar question, in an answer, Matthew Plourde suggested using getOption('run.main', default=TRUE) in the main script and then setting options(run.main=FALSE) before calling source(). This worked in my case.

Otherwise a simpler pattern when you have an R script creating a bunch of functions and you want to write a few lines at the end of the script to experiment with the use of a function: place these extra lines in an if(FALSE){} block.

Solution 6 - Python

This works fairly well for my use. If you have two files and want to source one with the other while only running a certain part of the file.

parent file: parent.R

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

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

child file: 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__`))
}

Output when running Rscript parent.R

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

Output when running Rscript child.R

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

A more robust method would be to write a custom source function where a list of arguments can be included.

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"))

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiongappyView Question on Stackoverflow
Solution 1 - PythonHarlanView Answer on Stackoverflow
Solution 2 - PythonedwindjView Answer on Stackoverflow
Solution 3 - PythonVinceView Answer on Stackoverflow
Solution 4 - PythonmcandreView Answer on Stackoverflow
Solution 5 - PythonPaul RougieuxView Answer on Stackoverflow
Solution 6 - Pythonzouth0View Answer on Stackoverflow