So, I am trying to run a python script in my Laravel 5.3.
This function is inside my Controller. This simply passes data to my python script
public function imageSearch(Request $request) {
    $queryImage = 'c:\\\xampp\\\htdocs\\\identificare_api\\\public\\\gallery\\\herbs\\\query.png'; //queryImage
    $trainImage = 'c:\\\xampp\\\htdocs\\\identificare_api\\\public\\\gallery\\\herbs\\\2nd.png'; //trainImage
    $trainImage1 = 'c:\\\xampp\\\htdocs\\\identificare_api\\\public\\\gallery\\\herbs\\\3rd.png';
    $trainImage2 = 'c:\\\xampp\\\htdocs\\\identificare_api\\\public\\\gallery\\\herbs\\\4th.jpg';
    $trainImage3 = 'c:\\\xampp\\\htdocs\\\identificare_api\\\public\\\gallery\\\herbs\\\1st.jpg';
    $data = array
        (
            array(0, $queryImage),
            array(1, $trainImage),
            array(3, $trainImage1),
            array(5, $trainImage2),
            array(7, $trainImage3),
        );
    $count= count($data);
    $a = 1;
    $string = "";
    foreach( $data as $d){
        $string .= $d[0] . '-' . $d[1];
        if($a < $count){
            $string .= ","; 
        }
        $a++;
    }
    $result = shell_exec("C:\Python27\python c:\xampp\htdocs\identificare_api\app\http\controllers\ORB\orb.py " . escapeshellarg($string));
    echo $result;
}
My python script is an ORB algorithm where it returns the smallest distance and its id after comparing the train images to the query image. So, this is my python script:
import cv2
import sys
import json
from matplotlib import pyplot as plt
arrayString = sys.argv[1].split(",")
final = []
for i in range(len(arrayString)):
    final.append(arrayString[i].split("-"))
img1 = cv2.imread(final[0][1], 0)
for i in range(1, len(arrayString)):
    img2 = cv2.imread(final[i][1], 0)
    # Initiate STAR detector
    orb = cv2.ORB_create()
    # find the keypoints and descriptors with SIFT
    kp1, des1 = orb.detectAndCompute(img1,None)
    kp2, des2 = orb.detectAndCompute(img2,None)
    # create BFMatcher object
    bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
    # Match descriptors.
    matches = bf.match(des1,des2)
    # Sort them in the order of their distance.
    matches = sorted(matches, key = lambda x:x.distance)
    # Draw first 10 matches.
    img3 = cv2.drawMatches(img1,kp1,img2,kp2,matches[:10], None, flags=2)
    if i == 1:
       distance = matches[0].distance
    else:
       if distance > matches[0].distance:
           distance = matches[0].distance
           smallestID = final[i][0]
print str(smallestID) + "-" + json.dumps(distance)
I already tried running both file without using Laravel and it is working well. But when I tried to integrate the php code to my Laravel, it displays nothing. The Status code is 200 OK.
EDIT: Problem Solved. In PHP code, just change
$result = shell_exec("C:\Python27\python c:\xampp\htdocs\identificare_api\app\http\controllers\ORB\orb.py " . escapeshellarg($string));
to
$result = shell_exec("python " . app_path(). "\http\controllers\ORB\orb.py " . escapeshellarg($string));
then, you can also do like this
$queryImage = public_path() . "\gallery\herbs\query.png";
                To run a Python script from PHP, we can use the shell_exec function. $command = escapeshellcmd('/usr/custom/test.py'); $output = shell_exec($command); echo $output; to call escapeshellcmd to escape the command string. Then we call shell_exec to run the $command .
Use Symfony Process. https://symfony.com/doc/current/components/process.html
Install:
composer require symfony/process
Code:
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
$process = new Process(['python', '/path/to/your_script.py']);
$process->run();
// executes after the command finishes
if (!$process->isSuccessful()) {
    throw new ProcessFailedException($process);
}
echo $process->getOutput();
                        The solution that worked for me was to add 2>&1 to the end.
shell_exec("python path/to/script.py 2>&1");
The issue I was having was no error and no response, I had the wrong path to the script but no way of knowing. 2>&1 will redirect the debug info to be the result.
In the shell, what does " 2>&1 " mean?
Would be handy to use Symfony Process. https://symfony.com/doc/current/components/process.html
Make sure symfony is available to use in your project
composer show symfony/process
If not installed do composer require symfony/process
And then do some thing like
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
//$process = new Process('python /path/to/your_script.py'); //This won't be handy when going to pass argument
$process = new Process(['python','/path/to/your_script.py',$arg(optional)]);
$process->run();
// executes after the command finishes
if (!$process->isSuccessful()) {
    throw new ProcessFailedException($process);
}
echo $process->getOutput();
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With