Using External Code in Production
While Workbench has built-in support for Java and PHP, you can also run scripts written in other programming languages such as R, Python, and Scala. To run a different language's script, the script needs to be capable of running from the command line and you need access to the language’s executable file in the command line. External scripts are run from the Execute Process Node in Production scripts.
For example, here is a breakdown of a valid command line string:
C:\R\R-4.1.2\bin\x64\Rscript.exe C:\R\fileIO.r "C:/DI/Projects/TestProject/" "test.txt"
-
Executable file path—The executable file path to the program that runs your language's script. In this example, Rscript.exe can run any R script that is passed to it.
-
Script file path—The file path to the script you want to run. Your script can reference and call other scripts, but only one script can be provided per command line.
-
Arguments—Each parameter for a script is entered in the command line, surrounded by quotation marks and separated by spaces.
TIP: If a file or folder in your file path has a space in its name, use quotation marks around that segment of the path. For example: C:\"Program Files"\Test\Example.txt
After adding a command line string to an Execute process node, you can use the Production script as is or package it into a Production extension. For more information on creating Production extensions, see Production Extensions Overview.
-
Create an Execute process node in a Production script.
For more information about adding an Execute process node, see Adding Nodes.
-
Open the Execute process node attributes pane.
-
Add a command line string, formatted as shown in the previous example.
In this example, the code takes in three arguments:
-
A working directory
-
An input file path
-
An output file path
This code turns an input csv file into an output tab-separated text file. A command line string for this script might look like this:
C:\R\R-4.1.2\bin\x64\Rscript.exe C:\R\fileIO.r "C:/DI/Projects/Student Project Production Training/" "data/transactions/accounts.csv" "test.txt"
## Example: fileIO.r: Parametrized R program that reads a file from one location and writes it to another location
## Read the arguments that are supplied when the R program is evoked.
args <- commandArgs(trailingOnly = TRUE)
## Assign the arguments to variables where args[1] is the working directory under which the files are located, args[2] is the input file name, and args[3] is the output file name.
working_dir <- args[1]
input_path <- args[2]
output_path <- args[3]
## Set the working directory. The input and output files must be in this directory or in a subdirectory of this directory.
setwd(working_dir)
print(getwd())
## Read the tab-separated input file as specified in args[2].
data <- read.csv(input_path, sep="\t")
## Write the tab-separated output file as specified in args[3]. Do not use quotes in the column names; Do not use row names.
write.table(data, file=output_path, sep="\t", col.names=TRUE, quote=FALSE, row.names=FALSE)
In this example, the code takes in three arguments:
-
A working directory
-
An input file path
-
An output file path
This code turns an input csv file into an output tab-separated text file. A command line string for this script might look like this:
C:\Users\AppData\Local\Programs\Python\Python310\python.exe C:\Python\FileIO.py "C:/DI/Projects/Student Project Production Training/" "data/transactions/accounts.csv" "test_py.txt"
import csv
import argparse
## Example: fileIO.py: Parametrized Python program that reads a file from one location and writes it to another location
## Create our arguments from the command line that will be parsed upon running.
parser = argparse.ArgumentParser(description='The working directory and input/output file paths.')
parser.add_argument('working_dir', help='The working directory to use input/output on')
parser.add_argument('input', help='The file path to the input file.')
parser.add_argument('output', help='The file path for the output file to go to.')
## Turn the argument values into an object we can access for processing.
args = parser.parse_args()
## Set the working directory. The input and output files must be in this directory or in a subdirectory of this directory.
p = args.working_dir
## Read the tab-separated input file as specified in args.input.
with open(p + args.input, 'r', newline='') as csvfile:
reader = csv.reader(csvfile, delimiter=',')
## Make a writer object with the file path from args.output
with open(p + args.output, 'w') as newtabfile:
writer = csv.writer(newtabfile, dialect='excel-tab')
for row in reader:
## Go row-by-row through the input file and write it to the output path.
writer.writerow(row)
In this example, the code takes in three arguments:
-
A working directory
-
An input file path
-
An output file path
This code turns an input csv file into an output tab-separated text file. A command line string for this script might look like this:
cs launch scala3-compiler:3+ -M dotty.tools.MainGenericRunner -- C:\Scala\FileIO.scala C:/DI/Projects/"Student Project Production Training"/ data/transactions/account.csv test_scala.txt
import scala.io.Source
import java.io._
//Example: fileIO.scala: Parameterized scala program that reads a file from one location and writes it to another location
object FileIO {
def main(args: Array[String]): Unit = {
//The arguments come in as a zero-indexed array that can be accessed with no extra work.
val working_dir = args(0);
//Create a file writer object that will output to a combination of the working directory and output file path.
val bufferedPrintWriter = new BufferedWriter(new PrintWriter(new File(working_dir.concat(args(2)))));
for (line <- Source.fromFile(working_dir.concat(args(1))).getLines) {
//Replace each comma with a tab separator and then write a new line
bufferedPrintWriter.write(line.mkString.replace(",", "\t"));
bufferedPrintWriter.newLine();
}
}
}