Accessing python nltk with php fails - php

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.

Related

Running complicated ROS shell command through php

I'm trying to run a ROS shell program on the server through php on Ubuntu 14.04. I have tried using system, exec, shell_exec but nothing happens and I don't get any output. The system call is the following:
echo shell_exec("/opt/ros/indigo/bin/rosrun gazebo_ros spawn_model -database Part_A -gazebo -model Part_A");
What are the limitations of using system or exec to run any shell command through php on a server?
I don't care as much about the output of the command as for its execution. I think the problem has to do with the fact that PHP doesn't have any PATH like shell does so it can't find any applications without specifying the exact location. How can I make PHP se the same PATH shell does?
The problem was that the apache user and the environment in which the bash commands are running are not set up correctly. I followed the instructions from this answer but instead of using "source" I used "." and instead of using the source.bash file I used the source.sh file. I also set all the environment variables that had to do with ros or gazebo using the putenv() function.

Is it possible to programmatically launch the php interactive shell from a file?

I would like to be able to either launch php in interactive mode via phing or via PHP (worst case scenario, phing can run an adhoc task with the desired code).
I've gotten this far:
<?php
$cmd = 'php -d auto_prepend_file=bootstrap.php -a';
passthru($cmd)
And the above almost gets me what I want. I enter a shell I can interact with, but the prompts are gone (the php > at the start of each line), all meta-commands (e.g., \>) totally fail, and typing exit; does nothing instead of exit the shell. So, as you can see, this isn't the ideal shell. Is this even possible without installing phpsh?
Thanks in advance.
I think PsySH will give you want you want. It's a PHP REPL that gives you the option to configure it to automatically include a bootstrap file.

Calling specific version of python from PHP

I'm setting up a big system relying on python 2.7 being run through php. The call is always something like:
exec('python test.py');
However no matter what I do PHP keeps using python 2.4 for executing my files. Because of the size of the system I can't change in the programming, but will have to make 'python' point directly to python2.7.
By searching around I have reached the conclusion that I should change the php env.
echo getenv("PYTHONPATH"); // NOTHING
echo getenv("PATH"); // /bin:/usr/bin
I can do so through putenv (for example: putenv("PATH=/usr/bin/python2.7:".$_ENV["PATH"]), but php keeps running python 2.4 no matter what I change it to.
Hope somebody out there got a simple solution :)
Could you not just do this instead:
exec('/usr/bin/python2.7/python test.py');
another option, you can set path to interpreter in 1st line of script test.py
#!/usr/local/bin/python2.7
but you need make test.py executable
chmod +x path_to_file/test.py
and run from php as
exec('path_to_file/test.py');
P.S. be attentive administrators sometimes disable exec function on servers for safety.
disable_functions="popen,exec,system,passthru,proc_open,shell_exec" ....
If you can't use full path, try an alias:
alias python='/usr/bin/python2.7'
python --version
Python 2.7.2

Running shell_exec() in symfony

I have a program that returns a comma-separated string of numbers after doing some background processing. I intended to run this in symfony using shell_exec; however, all I get is NULL (revealed through a var_dump(). I tried the following debugging steps.
I ran the file (it's a PHP class) through a command-line lime unit test in Symfony - it works and gives the correct result there.
Just to check, I tried a simple command ls -l at the same place to see whether I would get anything. Again, I had the same problem - the var_dump in the browser showed NULL, but it worked through the command line.
What could be the problem? Are there restrictions on running shell_exec() in a browser?
EDIT: Just to clarify, shell_exec() commands work when I run them as standalone php scripts on the web server (for example, by putting them in my document root. They don't seem to be working under the symfony framework, for some reason.
I finally solved it, and it turned out to be something quite simple, and quite unrelated.
The shell command I was running was in this format: face_query -D args. I didn't realize that Apache would be executing PHP as user www-data and thus the program face_query wouldn't be in the PATH (the directory is actually ~/bin). Changing the program name to the full path of the program solved it.
I also gather from this that only commands which www-data has permission to execute can be run. In this case, www-data is in the same group as my user, but it might be a problem otherwise.
Have you tried using exec? Or one of the other variants. I am never sure of which one to use and always lump with exec.
http://uk.php.net/manual/en/function.exec.php
Is your web server running php in safe mode?
Note: This function is disabled when PHP is running in safe mode.
From: http://php.net/manual/en/function.shell-exec.php

Unexpected behavior when calling a Ruby script via PHP's shell_exec()

I have a Ruby script that's being used to do some API calls/screen scraping, but our main app is in PHP. Our PHP app is using shell_exec() to call the Ruby script.
The ruby script works great when called from the command lineā€“but it will randomly exits early when called via PHP's shell exec.
Here's an example of the Ruby script:
#!/usr/bin/env ruby
require 'rubygems'
require 'mysql'
require 'net/http'
require 'open-uri'
require 'uri'
require 'cgi'
require 'fileutils'
# Bunch of code here ... works fine
somePath = 'http://foo.com/bar.php'
# Seems to always exit when I do a Net::HTTP or open-uri call
post = Net::HTTP.post_form(URI.parse(somePath),{'id'=>ID,'q'=>'some query'})
data = post.body
# OR
data = open(somePath).read
# More code here ...
So, all I can deduce so far is that it's always exiting when I try to grab/read an external URL via net/http or open-uri calls. The pages I'm grabbing can accept POST or GET requests, but it seems to be exiting either way.
I'm outputting the results with PHP after the shell_exec call, but there are no error messages or exits. I do have messages being output by my Ruby script with "puts ...." here and there. Could that be a problem (I'm thinking 'no' because it doesn't exit with earlier puts messages)?
Again, it works fine when called from the shell. It's almost like the shell_exec call isn't waiting for the net/http call to finish.
Any ideas?
I'm not sure on this, but given your explanation, which sounds plausible, have you looked at all at proc_open:
http://us3.php.net/proc_open
Ruby's open-uri requires tempfile, so I'm guessing there's a file ownership conflict between you running your ruby script and the web server running it. Can the web server create a temp file using tempfile?
Just an FYI, I never really uncovered why this was happening. The best I could deduce was that some type of permission issue was preventing Ruby's open-uri commands from working properly.
I opted for queuing these jobs in a db table and running my ruby script via cron periodically. Everything seems to work fine when the ruby script runs with root/sudo perms.
Run on Linux terminal:
sudo -H -u <user> bash -c <your code> where <user> is the Apache's user.
To find Apache's user you can echo("shell_exec(\"whoami\")"); inside your code and run it on browser. whoami works on Linux and Windows, but if you're under Windows, the Apache default user is your user. You can test it anyway in case it's different, but I can't tell how to run the code on Windows like if it's Apache running it.
After that you can have a clue of what's happening. In most cases the problem is the Apache's root folder is different from operating system's folder. So when you run a command with absolute path, the OS consider / and Apache consider /var/www/html on Linux, /opt/lampp/htdocs on Xampp(Linux) and C:/xampp/htdocs on Xampp(Windows). You get the idea i think.

Categories