31

Is it possible to run a Python script within PHP and transferring variables from each other ?

I have a class that scraps websites for data in a certain global way. i want to make it go a lot more specific and already have pythons scripts specific to several website.

I am looking for a way to incorporate those inside my class.

Is safe and reliable data transfer between the two even possible ? if so how difficult it is to get something like that going ?

Lee Taylor
  • 7,761
  • 16
  • 33
  • 49
Neta Meta
  • 4,001
  • 9
  • 42
  • 67

5 Answers5

74

You can generally communicate between languages by using common language formats, and using stdin and stdout to communicate the data.

Example with PHP/Python using a shell argument to send the initial data via JSON

PHP:

// 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)));

// Decode the result
$resultData = json_decode($result, true);

// This will contain: array('status' => 'Yes!')
var_dump($resultData);

Python:

import sys, json

# Load the data that PHP sent us
try:
    data = json.loads(sys.argv[1])
except:
    print "ERROR"
    sys.exit(1)

# Generate some data to send to PHP
result = {'status': 'Yes!'}

# Send it to stdout (to PHP)
print json.dumps(result)
Tom van der Woerdt
  • 29,532
  • 7
  • 72
  • 105
  • 2
    your php example looks pretty simple – Neta Meta Dec 27 '12 at 00:46
  • 1
    There's nothing hard about it, no! As long as you stick with standard data structures (string, int, array, dictionary, boolean, float), this approach will let you pass anything you need. – Tom van der Woerdt Dec 27 '12 at 01:38
  • 4
    Where it is supposed to be script.py? i got null in php page! – postgres Jun 09 '13 at 17:57
  • Can you also give example of sending data from python to php please? – Aditya Jun 24 '13 at 12:21
  • it's the same of the answer – postgres Jul 19 '13 at 07:52
  • 6
    If you are experiencing the `NULL` return from the python script, it may mean that `escapeshellarg()` is taking the double quotes away from the encoded JSON, rendering it invalid JSON, therefore causing `json.loads()` to fail. Try using `base64_encode();` instead of `escapeshellarg();` in php and `import base64`/`base64.b64decode()` in python. Also, don't forget to wrap your path in double quotes if it contains spaces `'python "path/that/has spaces/script.py" '` as was my case. Cheers! :) – Brian Mar 13 '14 at 18:36
  • @Brian: I was losing the double quotes in python without escapeshellarg(), and escapeshellarg() solved that problem. Still, thanks for mentioning base64, I will try that if I have more problems. – atmelino Jan 09 '16 at 02:03
  • This was super helpful for a Python newbie. Here is the output I received: array(1) { ["status"]=> string(4) "Yes!" } - as expected. Thanks. –  Jul 15 '18 at 23:02
  • In my case on apache server installed python 3.6. escapeshellarg(); works well. not the escapeshellcmd(); it works but it hardcodes character sets – Khalid Lakhani Jul 31 '21 at 07:44
10

You are looking for "interprocess communication" (IPC) - you could use something like XML-RPC, which basically lets you call a function in a remote process, and handles the translation of all the argument data-types between languages (so you could call a PHP function from Python, or vice versa - as long as the arguments are of a supported type)

Python has a builtin XML-RPC server and a client

The phpxmlrpc library has both a client and server

There are examples for both, Python server and client, and a PHP client and server

dbr
  • 165,801
  • 69
  • 278
  • 343
2

Just had the same problem and wanted to share my solution. (follows closely what Amadan suggests)

python piece

import subprocess

output = subprocess.check_output(["php", path-to-my-php-script, input1])

you could also do: blah = input1 instead of just submitting an unnamed arg... and then use the $_GET['blah'].

php piece

$blah = $argv[1];



if( isset($blah)){

    // do stuff with $blah

}else{
    throw new \Exception('No blah.');
}
fchaubard
  • 91
  • 4
0

The best bet is running python as a subprocess and capturing its output, then parsing it.

$pythonoutput = `/usr/bin/env python pythoncode.py`;

Using JSON would probably help make it easy to both produce and parse in both languages, since it's standard and both languages support it (well, at least non-ancient versions do). In Python,

json.dumps(stuff)

and then in PHP

$stuff = json_decode($pythonoutput);

You could also explicitly save the data as files, or use sockets, or have many different ways to make this more efficient (and more complicated) depending on the exact scenario you need, but this is the simplest.

Amadan
  • 191,408
  • 23
  • 240
  • 301
0

For me the escapeshellarg(json_encode($data)) is giving not exactly a json-formatted string, but something like { name : Carl , age : 23 }. So in python i need to .replace(' ', '"') the whitespaces to get some real json and be able to cast the json.loads(sys.argv[1]) on it.

The problem is, when someone enters a name with already whitespaces in it like "Ca rl".

Morizzla
  • 23
  • 6