PHP in python through bash - php

As I am messing around with Python, I wanted to write an application that would have its own web server. I am currently using a written code from this website for http server: Python Web Server and this is the direct link of the script
This script can handle html but I wanted to add php to it too. Since I know that in Ubuntu I can run php commands within the terminal, I wanted to implement the same logic to this script.
I added these lines:
import os
os.system('php '+filepath)
However my plan didn't go as well as planned... The "<? echo 'hello world'; ?>" that was in my test.php echoed the string to the terminal that ran the webserver.py and it only returned the output message "0" to the web browser.
Is there a way to capture the output of the php file into a string in bash so that I can make the python webserver script output that string with os.system ?
I'm using Ubuntu 11.10.

You can use getoutput from the commands package for this simple case.
from commands import getoutput
response = getoutput('php myscript.php')

You should eschew the use of os.system() in favor of the more modern subprocess module.
You might especially look at popen.communicate().

Related

How to get result from a command executed in PHP on remote SSH server using PuTTY?

I'm trying to execute a command on my Raspberry Pi via SSH and get the result of it in my PHP script on my Windows machine. Currently I can execute the command on my RasPi, but I do not get any results back into the PHP script.
The code I'm Using for this:
<?php
$cmd = "C:\\path_to_putty\\putty.exe -ssh pi#RasPiIP -pw raspberry -m C:\\path_to_test.txt\\test.txt";
$result = shell_exec($cmd);
echo $result;
?>
For sending commands to my RasPi the code works. I have tested multiple times by as example changing test.txt to sudo reboot and it worked as intended.
I'm using PuTTY to send my command (test.txt is currently nfc-list which returns connected Scanners etc not important right here) to the RasPi.
What I want to achieve is that $result contains the returned data when my command is executed.
Is it even possible to do that? If yes how (any help appreciated). If no, are they maybe other ways to approach this?
Addressing the possible duplicate: I am using a Windows Machine and also I'm trying to get the result (of the one command) to reuse in my PHP script. In the other question, user is trying to save the full console log and save it to another file.
First, do not use PuTTY. PuTTY is a GUI application intended for an interactive use. Use Plink, which is command-line/console equivalent of PuTTY intended for command automation. Being a console application, it has a standard output, which can be read in PHP (PuTTY as a GUI application does not have standard output).
With Plink, you can also specify the command on Plink command line, so you do not need to create the test.txt command file.
In any case, there's no way to make PuTTY or Plink separate an output of command only (at least not from a command-line).
But what you can do, is to print some header/trailer to distinguish the start and end of the command output, like:
plink.exe -ssh pi#RasPiIP -pw raspberry "echo start-of-command && command && echo end-of-command"
And then in PHP, you can look for the start-of-command and end-of-command to identify what part of Plink output is really the command output.
In any case, you better use a PHP SSH library to achieve what you want, rather then driving an external application. For example phpseclib. But that's a completely different question.

'python' is not recognized as an internal or external command, operable program or batch file using PHP passthru()

I am trying to invoke my python script from php by using passthru() function. I have already done that successfuly and for development I used xampp , now at some moment I installed manually apache,php and other add-ons.
I also made changes to apache conf to make my python scripts work, some of them work when i invoke them directly via ajax,but scripts like this:
<?php
passthru("python C:/Apache24/htdocs/app1/pyscripts/export_zakup.py GARČIN
2>&1",$retval);
echo $retval;
?>
give me result like:
'python' is not recognized as an internal or external command, operable program or batch file. 1
Also when i copy python C:/Apache24/htdocs/app1/pyscripts/export_zakup.py GARČIN to my cmd it works properly.
I have already spent few hours trying to find out where the problem is but unsuccessfuly. Anyone knows where the problem is?
First, locate where the Python executable is by runniing which python from the command line:
$ which python
$ /usr/bin/python
Then use the full path to the executable in your PHP script:
passthru("/usr/bin/python C:/Apache24/htdocs/app1/pyscripts/export_zakup.py GARČIN
2>&1",$retval);
echo $retval;
Keep in mind that the path will be different on Windows vs. Linux based machines. For example the latest versions on Windows typically install the executable in C:\Python27\, so the full path would be C:\Python27\python

Python Web Server with PHP code? [duplicate]

For some reason, I have to run a php script to get an image from Python. Because the php script is very big and it is not mine, it will takes me days to find out the right algorithm used and translate it into python.
I am wonder if there is any way to run php script, with few parameters, which returns a image, in python.
Example code:
import subprocess
# if the script don't need output.
subprocess.call("php /path/to/your/script.php")
# if you want output
proc = subprocess.Popen("php /path/to/your/script.php", shell=True, stdout=subprocess.PIPE)
script_response = proc.stdout.read()
You can simply execute the php executable from Python.
Edit: example for Python 3.5 and higher using subprocess.run:
import subprocess
result = subprocess.run(
['php', 'image.php'], # program and arguments
stdout=subprocess.PIPE, # capture stdout
check=True # raise exception if program fails
)
print(result.stdout) # result.stdout contains a byte-string
You can use php.py. This would allow you to execute php code in python, like in this example (taken from here):
php = PHP("require '../code/private/common.php';")
code = """for ($i = 1; $i <= 10; $i++) { echo "$i\n"; }"""
print php.get_raw(code)
If you can run the PHP script locally from the command-line, subprocess.check_output() will let you can PHP and will capture the return value.
If you are accessing PHP via a socket, then you can use urllib.urlopen() or urllib.urlretrieve() to pull down the resource.
Make a wrapper around the PHP script, which:
performs the stuff (If I understand well, it's an image creation),
then redirects (301 Moved Permanently) to the result image,
(also, the image should be purged some day).
So you can refer to this service (the PHP script) with a simple HTTP request, from anywhere, you can test it with browser, use from Python prg, you need just download the image the usual way.
Also, if you have a such standalone sub-system, don't feel bad about implement it with different language/technique. It has several advantages, e.g. you can install that service on a different host.
Recommended reading: Service-Oriented Architecture on Wikipedia.

Accessing python nltk with php fails

Im trying to call a python file containing a sentence/word tokenizer from my php file like this:
$output = shell_exec('python tokenizer.py $sentence')
I've tried single exec, full paths to python and tokenizer.py, wrapping $sentence in double quotes. But logically, It should not be the problem because calling print(1) at the beginning of python the python code before actually using any nltk packages makes $output equal to '1'. So I came to conclusion that the problem here is the nltk itself, like the path to the modules is not correct or something...
But, calling python from the shell using the same command as above gives me fully tokenized output! To conclude: looks like when calling python from php magically 'turns off' nltk, while it fully works when executed from the shell.
Here's the part of the python code I am using:
import sys
import nltk
from nltk.tokenize import sent_tokenize
sample_text2 = sys.argv[1]
gust = sent_tokenize(sample_text2)
#print(1) here doesn't work, but everywhere above (before calling sent_tokenize) it does.
The server's running on CentOS (Linux), I am accessing it via SSH.
Obvious question: What am I doing wrong here with PHP? Or generally? Any alternatives?
EDIT
As visible in dvhh's answer and its comments, the situation happened because there were two versions installed on the server (2.6 and 2.7), while the www user had access to 2.6 and through console, the default version was 2.7. The solution was to change the default python to 2.7 for both cases and to put the nltk modules to one of the dependency folders. (Or append the dependency directory using sys.path.append)
Your php script is executed by the www user.
You could check if the python script interpreter is correctly called, it is usually in one of the directory in the PATH environment variable (like /usr/bin/python), but the www user don't have a PATH environment variable set.
Solution specify the whole path to your python interpreter in your shell_exec call ( also specify the full path to your script when you're at it )
What about the path the nltk library is installed, you could check if the python interpreter would correctly look for it by looking at the sys.path while running python with the www user.
Diagnostic : use the shell_exec call to run a python script to print the sys.path values
Solution : append the library path to the sys.path in your python script before the import nltk
These would be the most obvious solutions considering the information provided in the question.
Update :
As there is 2 version version of python installed (on that haven't got the library installed ), it is recommended to specify the path to the desired interpreter. The first solution help correct the issue.
In unix like system I would recommend using which python command to determine the path of your default python interpreter.
Option 1
Setup a simple python httpserver listening on localhost. This old answer might help but there are plenty of howtos out there. The advantage is that you don't have the overhead of starting the python interpreter each time the ntlk stuff needs to be executed and you don't have to worry about shell script executions, permissions etc. Disadvantage is a little of extra work and a little overhead.
Option 2
Using a task queue. Whatever said and done it's not safe to execute commands from your web facing PHP scripts. If you are already using RabbitMQ or something similar you can use that here. Or else if you are using redis you can use the lpush, rpop methods to make redis behave like a queue. Disadvantage: the result is not immidiately available.
Option 3
Anbother strategy for your php script to enter the data into a table and setup your python script to run as a cron job to check the table once a minute. Disadvantage: the result is not immidiately available.
Option 4
Your current choice but please make sure that you have escaped the data properly by #lafor if this option is chosen #dvhh 's answer ought to work.
In my case it wasn't problem of python version but problem (as I soon found) of the nltk_data folder. First I thought it was as permission problem, so I changed the permissions to 777, but that didn't work.
I had to copy the folder.
First you have to find where was the nltk folder installed. You will find it by running python3 command from your bash and then put following lines:
import nltk
nltk.download('punkt')
nltk.download('averaged_perceptron_tagger')
It will say something like:
[nltk_data] Downloading package punkt to /root/nltk_data...
[nltk_data] Package punkt is already up-to-date!
Now you know you have it installed eg in /root folder (i had it there).
Then put in your python script which is called by php this:
import nltk
print(nltk.data.path)
It will output something like: (note the folders are another if you run it from php script or if you call it from command line)
['/var/www/nltk_data', '/usr/nltk_data', '/usr/share/nltk_data', '/usr/lib/nltk_data', '/usr/share/nltk_data', '/usr/local/share/nltk_data', '/usr/lib/nltk_data', '/usr/local/lib/nltk_data']
Now just copy your original folder to any of the above folders. I did:
cp /root/nltk_data /var/www/nltk_data -r
Voila. It works now.

How to run php in an HTML file running python?

I get an "unhandled exception" every time I try to run this standard include in an html file running python:
<?php
//add header with tabs
include('includes/templates/common/tpl_header.php');
?>
I'm trying to run it right under the body tag that looks like this:
<body py:match="body" py:attrs="h.append_class_attr(attrs, 'mcore-body')" py:with="
attrs = h.attrs_to_dict(select('#*'));
body_class = attrs.get('class', '').split(' ');
advertising_banner_html = g.settings['advertising_banner_html'];
">
... sorry but I'm not the most avid programmer, how do you get that puppy to run?!
HTML is HTML, Python is Python and PHP is PHP.
It's THREE different technologies, which cannot be mixed.
You can't "run standard PHP include" in HTML file.
You can't "run standard PHP include" in Python file.
You can run PHP code in PHP file only.
You can't run Python code in HTML file. You can run Python code in Python file only.
So, whole question makes no sense.
It seems you should forget PHP while working with Python and use Python features for including files. Of course it shouldn't be PHP file, but Python or at least HTML file
You can't "run" PHP inside Pytho.
Genshi has xi:include but that can include only local files.
It can apparently somehow be tricked into loading data from remote URLs - Here's an answer with some pointers (but no ready-made solution) how to do it.
If you manage to make Genshi fetch a remote file, you can point it to a local PHP URL: http://localhost/scripts/myscript.php Be aware however that this will start a remote PHP instance, and probably be slower than a pure filesystem lookup.
I have been in this situation myself when customizing Trac installs. The workaround I always ended up using was having a PHP script run manually or frequently through a cron job, and write into a static file that can be included using xi:include.

Categories