I’m developing an application using Symfony 3.4 and I have to use some python scripts. I used Symfony’s Process Component to execute my python script and I got an Exit Code: 1 (General Error) that I don’t understand. Moreover, I saw that my expected output appears in the ErrorOutput, is that normal?
Here is my python script (index.py) :
import scipy.stats as stats import sys #Kendall Coefficient def kendallcoeff(x1,x2): tau, p_value = stats.kendalltau(x1,x2) return tau sys.exit(float(kendallcoeff(sys.argv[1],sys.argv[2]))) #sys.exit(sys.argv)
And in my php class, I have this code :
$process = new Process("python3 python/index.py",null,["arg1" => $timeArray,"arg2" => $speedArray]); $process->run();
When I uncomment sys.exit(sys.argv), I get the error output :
"['python/index.py']"
Which shows that my arguments are not correctly passed to my script.
I always get :
The command “python3 python/index.py” failed.
Exit Code: 1(General error)
Can someone explain to me why I get this?
Answer
The Python function sys.exit() is only intended to pass Python process exit status, not application results between processes. Call sys.exit(0)
if the Python process terminated normally. Call sys.exit(1)
or sys.exit("error-message-string")
if there was an error. Your Python code passes a float to sys.exit()
which evaluates to 1, causing Symfony Process to print the error message.
Instead, pass Python application results using print() to Symfony PHP. (See https://symfony.com/doc/3.4/components/process.html for several ways of getting the output of the Python process.)
Since $timeArray and $speedArray are arrays, passing them on the command line to Python is problematic because they may be treated as more than two arguments. So the below code passes the arrays as one JSON string.
Python script {symfony-base}/public/python/index.py) :
#!/usr/bin/python3 import json import scipy.stats as stats import sys def kendallcoeff(x1,x2): tau, p_value = stats.kendalltau(x1,x2) return tau print(sys.argv) json_data = sys.argv[1] python_obj = json.loads(json_data) timeArray = python_obj[0] speedArray = python_obj[1] print(kendallcoeff(timeArray,speedArray)) sys.exit(0)
PHP Symfony class src/Controller/KendallCoefficientController.php should look something like this:
<?php namespace AppController; use SymfonyBundleFrameworkBundleControllerAbstractController; use SymfonyComponentHttpFoundationResponse; use SymfonyComponentProcessExceptionProcessFailedException; use SymfonyComponentProcessProcess; use SymfonyComponentRoutingAnnotationRoute; class KendallCoefficientController extends AbstractController { /** * @Route("/kendall", name="kendall") */ public function index() { $timeArray = [1.0, 2.0, 3.0]; $speedArray = [10.1, 20.2, 30.3]; $arg = json_encode([$timeArray, $speedArray]); $process = new Process(['python3', 'python/index.py', $arg]); $process->run(); // executes after the command finishes if (!$process->isSuccessful()) { throw new ProcessFailedException($process); } $pyoutput = $process->getOutput(); $response = new Response($pyoutput, Response::HTTP_OK, ['content-type' => 'text/plain']); return $response; } }