How to properly call Python 3 script from PHP? - php

I would like to call a Python 3 script (with arguments) from PHP and process the returned information.
//server.php
arg1 = $_POST['arg1'];
arg2 = $_POST['arg2'];
args = array(arg1,arg2);
//pseudo code - THIS IS WHERE MY QUESTION IS
//$results = call_python3_script_somehow
echo $results
#script.py
import MyProcess
#take in args somehow
args = [arg1,arg2]
result = MyProcess(args)
return result
The problem is this has been asked many times on Stack Overflow, and there are different answers each one:
The execute function (here and here)
$output = array();
exec("python hi.py", $output);
var_dump( $output);
The escape shell function (here)
$command = escapeshellcmd('/usr/custom/test.py');
$output = shell_exec($command);
echo $output;
The shell execute function (here)
// This is the data you want to pass to Python
$data = array('as', 'df', 'gh');
// Execute the python script with the JSON data
$result = shell_exec('python /path/to/myScript.py ' . escapeshellarg(json_encode($data)));
The system function (here)
$mystring = system('python myscript.py myargs', $retval);
All of these answers are accepted and have a decent number of upvotes. Which, if any of these, is the proper way to call a Python script from PHP?

They all do the same thing but have some different output. I would suggest to use the one that best fits your scenario.
I often use shell_exec because it's easier for me on debugging since I all I need to do is just print a string out in <pre> tags. There's one thing that people tend to forget, especially when they are trying to debug stuff. Use: 2>&1 at the end of the script and the args. Taking one of the examples you have above, it would look something like this:
shell_exec('python /path/to/myScript.py ' . escapeshellarg(json_encode($data)) . " 2>&1");
This allows you to view error output as well, which is more than likely what you'll need to figure out why it's working on the command line, but it's not working when you run it from PHP.

Related

PHP exec returns empty string while executing Python script

I am trying to run a Python script inside PHP and show the output.
I tried with simple test.py inside PHP, which print hello world without problem. But when I try to execute my desired command from PHP script the exec() returns empty string instead of output.
So the here is my php script. Below snippets works fine:
$output = exec("python test.py");
var_dump($output);
But not the desired one.
$command = "python -m scripts.label_image --graph=tf_files/retrained_graph.pb --image=".$uploadfile;
$output = exec($command);
var_dump($output);
so the folder structure is:
/var/www/mysite/
-scripts(folder which contains python scripts)
-tf_files(folder with other files)
-uploads (image folder)
Can someone tell me what is going wrong?
Sample output in stdout/shell:
the variable $output should an argument.
If you do this, you should get only the last output of your script.
exec("python test.py", $output);
var_dump($output);
https://www.php.net/manual/en/function.exec.php

Passing arguments from PHP to a remote shell script

I am executing a shell script located on a remote machine from a PHP script. So, let's say that PHP script runs on A and shell script runs on B (10.0.0.37).
I have the following code which runs well
$cmd = "ssh 10.0.0.37 /usr/tmp/script.sh";
exec($cmd, $output);
Now, I want to pass arguments to the shell script, preferably in JSON format.
The output of echo json_encode($arg) is as follows:
[{"original_name":"pdf_convert","changed_name":"pdf_convert_1"},{"original_name":"video_encode","changed_name":"video_encode_1"},{"original_name":"video_transcode","changed_name":"video_transcode_1"}]
I want to pass this as an argument to the shell script. So,
$data = json_encode($data);
$cmd = "ssh 10.0.0.37 /usr/tmp/script.sh $data";
exec($cmd, $output);
However, I see that the argument is not correctly read by the shell script. I tried putting single quotes around $data, didn't work. Also, tried using escapeshellarg($data), still did not work.
Edit
The output of echo escapeshellarg($data) is
'[{"original_name":"pdf_convert","changed_name":"pdf_convert_1"},{"original_name":"video_encode","changed_name":"video_encode_1"},{"original_name":"video_transcode","changed_name":"video_transcode_1"}]'
Also, if there is any other format which can be parsed easily in a shell script, then I would lie to use that format (not necessarily JSON). I see that I may have to use 'jq' to parse json which needs me to install an additional package.
Bash isn't very good at accepting a JSON string in as arguments...
One way to get around bash trying to parse the arguments is for your php script to write the JSON string to a file, and for the bash script to parse that file with jq
I was able to use serilaize to send the json data. Below is the code.
$data = json_encode($arg)
$data = escapeshellarg($data);
$data = serialize($data);
$data = str_replace('"','\"',$data);
$cmd = "ssh 10.0.0.37 /usr/tmp/script.sh $data";
I can now get the data in the shell script.
PHP:
<?php
$json = '[{"original_name":"pdf_convert","changed_name":"pdf_convert_1"},{"original_name":"video_encode","changed_name":"video_encode_1"},{"original_name":"video_transcode","changed_name":"video_transcode_1"}]';
$cmd = $json;
$cmd = addslashes($cmd);
// addslashes does not escapes curly braces
$cmd = strtr($cmd, array('{' => '\\{', '}' => '\\}'));
$cmd = escapeshellarg($cmd);
$cmd = "ssh localhost echo $cmd";
echo "\n$cmd\n\n";
exec($cmd, $output);
var_dump($output)
Shell (/tmp/1.sh):
#!/bin/sh
echo "$1"
Shell Output:
ssh localhost /tmp/1.sh '[\{\"original_name\":\"pdf_convert\",\"changed_name\":\"pdf_convert_1\"\},\{\"original_name\":\"video_encode\",\"changed_name\":\"video_encode_1\"\},\{\"original_name\":\"video_transcode\",\"changed_name\":\"video_transcode_1\"\}]'
array(1) {
[0]=>
string(200) "[{"original_name":"pdf_convert","changed_name":"pdf_convert_1"},{"original_name":"video_encode","changed_name":"video_encode_1"},{"original_name":"video_transcode","changed_name":"video_transcode_1"}]"
}

Executing python commands from php script

I have installed SymPi in the server and from the command line, I am able to execute the following.
python ./sympy-0.7.5/bin/isympy
(this will open a console where I can type mathematical expressions. then the following expression)
1 + 2
(will give 3 as output)
My aim is to do the same from php using shell_exec. I have written a php file as given below, but is not working.
$command = escapeshellcmd('python ./sympy-0.7.5/bin/isympy');
shell_exec($command);
$output = shell_exec('1 + 2');
Can anybody help me to figure out why this is not working?
Please note that the following script works fine which just execute a python script and retrieve the output.
$command = escapeshellcmd('python C:\PythonPrograms\test3.py');
$output = shell_exec($command);
echo $output;
My guess is that the working directory (cwd) of shell_exec is different from the one you're in when you execute it manually.
Your working example specifies a hard path that will work from anywhere. Whereas your not-working example specifies a relative path (./ is the cwd).
Convert your call to isympy to give its full path on disk. Or figure out how to set the cwd of shell_exec.
(If this doesn't solve it, say more than "is not working." What happens? An error? What is the full text of the error?)
Each time you run shell_exec, it opens a completely new instance of the shell.
Edit:
You can pass a command for python to execute like this:
$expression = '1 + 2';
$cmd = 'python -c \'print "%f" % (' . $expression . ')\'';
$output = shell_exec($cmd);
This, admittedly is not using sympy, but for simple mathmatical expressions you may not need to. If you do, you would just need to import the library in the same command, like this: python -c 'import sympy; print "%f" % sympy.sqrt(3)'
I could manage the desired result in a different way.
Created a python script which accepts the expression as the command line argument , execute and display the output.
Call this script from php by passing the expression as the command line argument.

How can I get cmd result using php

i am using this code in php for using lucene file indexer and searcher but it results in empty array...
$resul = exec('set classpath=C:\lucene\lucene\core\lucene-core-4.3.0.jar;C:\lucene\lucene\queryparser\lucene-queryparser-4.3.0.jar;C:\lucene\lucene\analysis\common\lucene-analyzers-common-4.3.0.jar;C:\lucene\lucene\demo\lucene-demo-4.3.0.jar2>&1',$result);
echo $result;
$resul = exec('java org.apache.lucene.demo.IndexFiles -doc C:\lucene\src',$result);
echo $result;
$resul = exec('java org.apache.lucene.demo.SearchFiles');
echo $result;
Each instance of exec uses a separate environment from all the others. This means that the environment variables set by your first exec do not "stick" when the following calls are made, so the classpath is most likely empty and your Java programs fail to run.
The solution is to make everything into one big command line. On Windows you can do that by concatenating the commands with &:
// Sorry for the unreadable line, but it has to be without linebreaks
$commands = "set classpath=C:\lucene\lucene\core\lucene-core-4.3.0.jar;C:\lucene\lucene\queryparser\lucene-queryparser-4.3.0.jar;C:\lucene\lucene\analysis\common\lucene-analyzers-common-4.3.0.jar;C:\lucene\lucene\demo\lucene-demo-4.3.0.jar2 & java org.apache.lucene.demo.IndexFiles -doc C:\lucene\src & java org.apache.lucene.demo.SearchFiles";
exec($commands, $result);
With this arrangement $result will only contain the output from the last command run, but fortunately this looks like exactly what you want to do.

PHP Put list from Powershell into Array

Code:
$exchangesnapin = "Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010";
$output = shell_exec('powershell '.$exchangesnapin.';"get-mailboxdatabase" 2>&1');
echo( '<pre>' );
echo( $output );
echo( '</pre>' );
Result:
Name Server Recovery ReplicationType
---- ------ -------- ---------------
Mailbox Database 0651932265 EGCVMADTEST False None
Mailbox Database 0651932266 EGCVMADTEST False None
I tried with
echo( $output[1] );
The result was only a letter 'N'. I believe its taking the Name column but one character at a time.
$output[1] is 'N', $output[2] is 'a'.
Is there any way I can get the mailbox list into array?
you are trying to execute an external program (powershell) from PHP and have the output as an array.
In order to execute an external program in PHP, you could use:
exec() function
shell_exec() function
system() function
backtick operator
process control extensions
using process control extensions (PCNTL, popen) gives you more control, but takes more code and time. using the execution functions are simpler.
In this situation, using exec() could help you to have the output of powershell in an array whose each index is a line from the powershell output.
<?php
$output = array(); // this would hold the powershell output lines
$return_code = 0; // this would hold the return code from powershell, might be used to detect execution errors
$last_line = exec("powershell {$exchangesnapin} get-mailboxdatabase 2>&1", $output, $return_code);
echo "<pre>";
// print_r($output); view the whole array for debugging
// or iterate over array indexes
foreach($output as $line) {
echo $line . PHP_EOL;
}
echo "</pre>";
?>
Please note that (as the documentation says) if you only want to echo the output of powershell, you could use the passthru() function. using exec() uses memory to store the output of the external program, but using passthru would not use this storage, resulting in less memory usage. But the output could not be used for further processing, and is sent to the PHP standard output right a way.
In the end, please note that external program execution requires careful data validation to reduce the risk of unwanted system effects. Make sure you use escapeshellarg() on the data that constructs the execution command.

Categories