2

I would like to run an R script from python, and capture the output into a .Rout type file. The R script takes command line arguments. I am struggling... Minimal working example follows.

R script:

job_reference <- commandArgs(trailingOnly = TRUE)
arg1 <- job_reference[1]
arg2 <- job_reference[2]
arg3 <- job_reference[3]
arg4 <- job_reference[4]
print("***")
print(paste(arg1, arg2, arg3, arg4))
print("***")

python script:

import subprocess
arg1 = 'a'
arg2 = 'b'
arg3 = 'c'
arg4 = 'd'
subprocess.call(["/usr/bin/Rscript",  "--no-save", "--no-restore", "--verbose", "print_letters.R",  arg1, arg2,  arg3, arg4, ">", "outputFile.Rout", "2>&1"])

The last line in the python script is via this stackoverflow link.

If I run the python script, the "outputFile.Rout" is not produced. However the python output includes:

running
'/usr/lib/R/bin/R --slave --no-restore --no-save --no-restore --file=print_letters.R --args a b c d > outputFile.Rout'

and when I run that from the command line without involving python the output file is produced. Note that I have tried specifying full paths to output files, etc.

Can anyone explain i) what is happening here; ii) how I can run an R script from python with the R script accepting command line arguments and producing an Rout type file?

Thanks in advance.

Community
  • 1
  • 1

1 Answers1

4

i) what is happening here

The Rscript call you grabbed makes use of a shell feature called i/o redirection. In particular, the end of that command, > outputFile.Rout 2>&1 is a special shell feature that means roughly redirect all the output from the command into the file "outputFile.Rout", oh and also redirect standard error to standard out so it ends up in that file as well.

From the subprocess docs,

shell=False disables all shell based features

in other words, the default for subprocess.call() is to run the command without using the shell, so you don't get access to the shell based features. Instead the '>' and 'outputFile.Rout' for instance are passed directly as args to R, just like a.

ii) run R script with output redirect

While there a couple ways to go about this, such as using os.system() or passing shell=True to subprocess.call() and passing the command as a string, the recommended way is just to use the machinery in subprocess to do the equivalent i/o redirection:

with open('outputFile.Rout','w') as fileobj:
    subprocess.call(["/usr/bin/Rscript",  "--no-save", "--no-restore",
                     "--verbose", "print_letters.R", 
                     arg1, arg2,  arg3, arg4], 
                     stdout=fileobj, stderr=subprocess.STDOUT)
lemonhead
  • 5,328
  • 1
  • 13
  • 25