Error execution Python script from php in Apache2 - php

I'm creating a web application managed with apache2, the problem I'm trying to solve is running a python script using php, I'm attaching my code:
PHP CODE:
<?php
$command = escapeshellcmd("/usr/bin/python3.6 /var/www/html/yoloface-master/showInWeb.py");
$output = shell_exec($command);
echo $output;
?>
PYTHON CODE
#!/usr/bin/python3.6
import hashlib, os, sys, cv2, PIL, subprocess, glob, numpy, django, random
from PIL import Image
import shutil
def showInWeb():
pathYolo = 'yoloface-master/'
os.chdir(pathYolo)
photo = random.choice(os.listdir("../Database/ARCHIVIOIMAGO"))
path = '../Database/ARCHIVIOIMAGO/'
print(photo)
shutil.rmtree('outputs/')
processPhoto = path + photo
command_line = ('python3.6', 'yoloface.py', '--image', processPhoto, '--output-dir', 'outputs/')
print(subprocess.run(command_line))
showInWeb();
As IDE I'm using pyCharm, and if I run the same command line in the pyCharm terminal (I'm not in a virtual environment) the program works without problems, however if I run it through the php script I get an error like "No Module Named cv2 ", this makes me guess that php is using a different version.
I read on the internet that a possible solution was to place "sudo" on the command line like:
sudo /usr/bin/python3.6 /var/www/html/yoloface-master/showInWeb.py
But I get this error:
sudo: no tty present and no askpass program specified
How can I do?

Related

Having trouble executing Python script from PHP because of an ImportError

I'm trying to execute a Python script from PHP using exec() like this:
echo exec("/usr/bin/python3 timedttp.py 2>&1");
I get ImportError: No module named 'mpld3'. I'm running this with Apache on a Raspberry Pi. The Python program is located in the same directory as my php file, and whenever I run the script in the terminal there are no problems at all. Also tried using shell_exec() and the error I get is the following one:
Traceback (most recent call last): File "timedttp.py", line 6, in import matplotlib.pyplot as plt, mpld3 ImportError: No module named 'mpld3'
I'm calling the module like this inside my Python script:
import matplotlib.pyplot as plt, mpld3
I can run this program wihtout any issues from the terminal, so I think this is Apache or PHP related.
I'd really appreciate any help I can get with this.

Python modules are not imported when running python script from PHP

I have a Python script, which works fine when I run it in Terminal. Here it is:
import bs4, requests, json, sys
from sys import argv
def getFsmonData(link):
res = requests.get(link)
res.raise_for_status()
soup = bs4.BeautifulSoup(res.text)
# Get table data
tds = soup.select('td')
new_td_list = []
for i in range(len(tds)):
inner_td_list = []
for y in range(len(tds)):
inner_td_list.append(tds[y].getText())
new_td_list.append(inner_td_list)
print(inner_td_list)
td_list_json = json.dumps(inner_td_list)
tdf = open("/path/to/file/data/td_data.txt", "w")
tdf.write(td_list_json)
tdf.close()
getFsmonData(sys.argv[1])
But now I am trying to run it from PHP and I get the following error:
Traceback (most recent call last): File
"/path/to/file/example.py", line 1, in import bs4, requests,
json, sys ModuleNotFoundError: No module named 'bs4'
I guess PHP thinks I do not have this module installed, but I am not sure of course. Here is my PHP code:
<?php
$link = $_POST['dn-link'];
if (isset($_POST['submit'])) {
system('/usr/bin/python3 /path/to/file/example.py ' . escapeshellarg($link) . ' 2>&1', $retval);
}
?>
Who can help solving this issue?
Most likely, when your PHP script executes your Python script, its executing it as a different user (possibly super user). What you can do is check if the packages are installed under the super user by doing
sudo pip list
or if you're using python3
sudo pip3 list
see if the packages you we're wanting to use are listed from this command.
If they aren't listed, you can easily install them via the command:
sudo pip install <pkg name>
or
sudo pip3 install <pkg name>
What you're doing here is installing the packages under the super user rather than you the local user.
I think your misunderstanding the permission issue. It's not that you need to add it PHP. It's that your OS keeps track of permissions, and the permission you have assigned to your PHP interpreter and your Python interpreter are misaligned. There are two permissions that usually people mix up here - USER which is login level access and SYSTEM which is system wide access. If your on your own dev machine then add both to SYSTEM.
We need to know your OS to be able to fully answer, i'm going to guess Mac OS in which case would be this (I think, can't test it right now).
sudo nano "pathOfYourInterpreter"
The other thing could be happening is that the libraries you're tryng to import are somewhere where the current sys path you have setup can't reach them. For example if you have your sys variable for Python set to the directory where the interpretor is but the scripts you're importing are in a different folder. In that case you have several options for accessing those scripts.
Set the current working directory to the folder where they're located before importing with:
os.chdir("locationOfScript/")
import script.py
Add a sys Path at runtime:
sys.path.append("locationOfScript/)
There are more methods of attack, but I think this should get you started.

Invoking a python script from a PHP script

I am running a PHP web script locally for testing purposes through terminal with command: php -S localhost:8000.
<?php $command = '/usr/bin/python /Users/Jupiter/Desktop/NC/www/createHarbourContainter.py'; exec($command); ?>
I am trying to call this python script that exists in the same directory:
#!/usr/bin/python
import os
import sys
save_path = '/Users/Jupiter/Desktop/NC/harbours/'
name = sys.argv[1]
def newHarbourContainer():
os.makedirs(save_path + name)
def main():
newHarbourContainer()
if __name__ == '__main__':
main()
This python script has chmod x+ set to it.
I am able to run the python script from the terminal :python createHarbourContainter.py
What I am unable to do is get the PHP function exec() to invoke the python script. Help needed!
In PHP you can use backticks ` to execute shell commands, so try this:
<?php
`/usr/bin/python /Users/Jupiter/Desktop/NC/www/createHarbourContainter.py`
?>
See http://php.net/manual/en/language.operators.execution.php for more info
So I have found a solution:
$output = shell_exec('python createHarbourContainer.py')
And to get back an output into the browser:
echo "<pre>$output</pre>";
I was running the server in PHP Development Server.
Using bash command: php -S localhost:8000 from directory where index.php is located.
The server was logging all input and output from browser interface.
I realized that when calling: /usr/bin/python from php the PHP Development Serverwould halt and open python interpreter.
And setting the whole path to the python script I wanted executed didn't work because the PHP script didn't have permission.
How this can help someone else in future.

Script causes errors that don't happen when python run via command line

Previous Research:
Running a Python script from PHP
error on using exec() to call python script
Php exec python script 'weakness'/downside
Using exec() to run python script in PHP
I am running php version 5.6.6 and python version 3.4.3 on OS X.
Basically, the problem that I am running into is that if I run a python script via command line it works find but if I run it through a PHP script (using exec()) I get this error:
AttributeError: type object 'int' has no attribute 'from_bytes'
I have created and tested a miniature isolated test case to show the problem. I have already done a chmod 777 mypy.py to make sure mypy.py is executable.
myphp.php:
<?php
exec("/usr/bin/python mypy.py 1A", $output, $return);
var_dump($output);
mypy.py:
#!/usr/bin/env python
import string
import array
import binascii
import sys
if __name__ == "__main__":
hexval = sys.argv[1]
binval = binascii.unhexlify(hexval)
binint = int.from_bytes(binval, byteorder='big', signed=False)
print("int: " + str(binint))
(I know there are better ways to accomplish what is being done in this python script, I was just making a test case that would produce the same error)
When I run python mypy.py 1F via command line, I get this printed:
int: 31
But when I run php myphp.php via command line, I get this printed:
Traceback (most recent call last):
File "mypy.py", line 11, in <module>
binint = int.from_bytes(binval, byteorder='big', signed=False)
AttributeError: type object 'int' has no attribute 'from_bytes'
array(0) {
}
(Note: I have also executed whoami from the php script just to verify that my normal user is the one running the python script)
int has no method .from_bytes in python2,/usr/bin/python uses the python 2 interpreter, you need to use /usr/bin/python3 to use your python3 interpreter.
exec("/usr/bin/python3 mypy.py 1A", $output, $return);
Making the file executable is also irrelevant as you are explicitly running it with python.
To run it as an executable and use the python3 interpreter specify the correct python version in your python shebang:
#!/usr/bin/env python3
Then:
exec("./mypy.py 1A", $output, $return);
Sorry for previous edits, I misread the question. Are you sure that python in cli and /usr/bin/python resolve to the same binary? The behavior I see tells me PHP is trying to use Python 2.x (because int object doesn't have method from_bytes).

What is the difference between running a script from the command line and from exec() with PHP?

I'm trying to run a Python script using exec() from within PHP. My command works fine when I run it directly using a cmd window, but it produces an error when I run it from exec() in PHP.
My Python script uses NTLK to find proper nouns. Example command:
"C:\Python25\python.exe" "C:\wamp\projects\python\trunk\tests\find_proper_nouns.py" "I went to London this morning"
returns [London] when I run it from cmd, but throws an error in the Apache log when I run the same command from exec().The script is defintely getting run OK - if I change the python script to be print "Hello World" that is returned fine.
I know it's a big ask for anyone to know how to fix this NLTK error, but I could really do with any pointers as to why running it from exec is different to cmd. (The command is identical).
I'm running WAMP on Windows 7 with Apache 2.2.11.
Here's the error in the Apache log:
Traceback (most recent call last):
File "C:\wamp\projects\python\trunk\tests\find_proper_nouns_command_line.py", line 6, in <module>
parts = nltk.pos_tag(text)
File "C:\Python25\lib\site-packages\nltk\tag\__init__.py", line 62, in pos_tag
tagger = nltk.data.load(_POS_TAGGER)
File "C:\Python25\lib\site-packages\nltk\data.py", line 590, in load
resource_val = pickle.load(_open(resource_url))
File "C:\Python25\lib\site-packages\nltk\data.py", line 669, in _open
return find(path).open()
File "C:\Python25\lib\site-packages\nltk\data.py", line 451, in find
raise LookupError(resource_not_found)
LookupError:
**********************************************************************
Resource 'taggers/maxent_treebank_pos_tagger/english.pickle' not
found. Please use the NLTK Downloader to obtain the resource:
>>> nltk.download().
Searched in:
- 'C:\\nltk_data'
- 'D:\\nltk_data'
- 'E:\\nltk_data'
- 'C:\\Python25\\nltk_data'
- 'C:\\Python25\\lib\\nltk_data'
- 'C:\\Windows\\system32\\config\\systemprofile\\AppData\\Roaming\\nltk_data'
**********************************************************************
You have to run nltk.download() and choose 'maxent_treebank_pos_tagger'. You must make a python script and in it put:
#!/usr/bin/python
import nltk
nltk.download('maxent_treebank_pos_tagger');
then run it from command line. It will install the data files for the POS tagges, which you don't have installed yet.
After you do this it should work.
Your web server likely runs with other privileges than yourself. Possible problems include:
Path/file permission: can the web server user access the files it needs?
Different environment: are all necessary environment variables (PATH, Python-specific stuff, …) set?
Configuration: are there per-user configurations for Python or the module?
Tip: execute set in both the command prompt and from the PHP process and check the differences.
From the shell/terminal, you can use:
sudo python -m nltk.downloader maxent_treebank_pos_tagger
It will install maxent_treebank_pos_tagger (i.e. the standard treebank POS tagger in NLTK).

Categories