package org.molgenis.python;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
/**
* Executes a Python script with the Python version installed on server executable in a new process.
*/
@Service
public class PythonScriptExecutor
{
private static final Logger LOG = LoggerFactory.getLogger(PythonScriptExecutor.class);
private final String pythonScriptExecutable;
@Autowired
public PythonScriptExecutor(@Value("${python_script_executable:/usr/bin/python}") String pythonScriptExecutable)
{
if (pythonScriptExecutable == null)
{
throw new IllegalArgumentException("pythonExecutable is null");
}
this.pythonScriptExecutable = pythonScriptExecutable;
}
/**
* Execute a python script and wait for it to finish
*/
public void executeScript(File script, PythonOutputHandler outputHandler)
{
// Check if Python is installed
File file = new File(pythonScriptExecutable);
if (!file.exists())
{
throw new MolgenisPythonException("File [" + pythonScriptExecutable + "] does not exist");
}
// Check if Python has execution rights
if (!file.canExecute())
{
throw new MolgenisPythonException(
"Can not execute [" + pythonScriptExecutable + "]. Does it have executable permissions?");
}
// Check if the Pyhton script exists
if (!script.exists())
{
throw new MolgenisPythonException("File [" + script + "] does not exist");
}
try
{
// Create r process
LOG.info("Running python script [" + script.getAbsolutePath() + "]");
Process process = Runtime.getRuntime().exec(pythonScriptExecutable + " " + script.getAbsolutePath());
// Capture the error output
final StringBuilder sb = new StringBuilder();
PythonStreamHandler errorHandler = new PythonStreamHandler(process.getErrorStream(),
new PythonOutputHandler()
{
@Override
public void outputReceived(String output)
{
sb.append(output).append("\n");
}
});
errorHandler.start();
// Capture r output if an Python output handler is defined
if (outputHandler != null)
{
PythonStreamHandler streamHandler = new PythonStreamHandler(process.getInputStream(), outputHandler);
streamHandler.start();
}
// Wait until script is finished
process.waitFor();
// Check for errors
if (process.exitValue() > 0)
{
throw new MolgenisPythonException("Error running [" + script.getAbsolutePath() + "]." + sb.toString());
}
LOG.info("Script [" + script.getAbsolutePath() + "] done");
}
catch (IOException e)
{
throw new MolgenisPythonException("Exception executing PythonScipt.", e);
}
catch (InterruptedException e)
{
throw new MolgenisPythonException("Exception waiting for PythonScipt to finish", e);
}
}
}