PHP脚本无法获取Python脚本的输出
我在用PHP脚本执行一个Python脚本时遇到了问题。我的客户使用的是Bluehost,所以我按照这里的说明通过easy_install方法为Python安装了一个第三方模块(numpy):https://my.bluehost.com/cgi/help/530?step=530
为了展示我的问题,我创建了两个Python脚本和一个PHP脚本。
hello.py的内容是:
print "Hello, World!"
hello-numpy.py的内容是:
import numpy
print "Hello, World!"
PHP脚本的内容是:
Output from exec('python hello.py'): <?php echo exec('python hello.py'); ?><br>
Output from exec('python hello-numpy.py'): <?php echo exec('python hello-numpy.py'); ?><br>
Output from exec('whoami'): <?php echo exec('whoami'); ?>
然后我从PHP得到了这个输出:
执行exec('python hello.py')的输出:Hello, World!
执行exec('python hello-numpy.py')的输出:
执行exec('whoami')的输出:venicetw
然而,从SSH窗口运行这些脚本得到的结果是:
# python hello.py
Hello, World!
# python hello-numpy.py
Hello, World!
# whoami
venicetw
看起来当Python脚本导入numpy时,PHP没有得到任何输出,但在SSH中运行是正常的。此外,hello.py的返回状态是0,而hello-numpy.py的返回状态是1。我以为可能是权限问题,但PHP和SSH都是以“venicetw”用户身份运行的。是什么原因导致PHP和Apache无法获取Python脚本的输出呢?这是我可以和Bluehost讨论的问题,还是我应该检查其他东西?我们使用的是Apache 2.2.21
、PHP 5.2.17
、Python 2.4.3
和numpy 1.6.0
。
更新:SSH打印了以下Python路径:
/home8/venicetw/public_html/venicenoise/python
/home8/venicetw/.local/lib/python2.4/site-packages/ogcserver-0.1.0-py2.4.egg
/home8/venicetw/.local/lib/python2.4/site-packages/PIL-1.1.7-py2.4-linux-x86_64.egg
/home8/venicetw/.local/lib/python2.4/site-packages/lxml-2.3.2-py2.4-linux-x86_64.egg
/home8/venicetw/.local/lib/python2.4/site-packages/WebOb-1.2b2-py2.4.egg
/home8/venicetw/.local/lib/python2.4/site-packages/PasteScript-1.7.5-py2.4.egg
/home8/venicetw/.local/lib/python2.4/site-packages/PasteDeploy-1.5.0-py2.4.egg
/home8/venicetw/.local/lib/python2.4/site-packages/Paste-1.7.5.1-py2.4.egg
/home8/venicetw/.local/lib/python2.4/site-packages/numpy-1.6.0-py2.4-linux-x86_64.egg
/home8/venicetw/.local/lib/python2.4/site-packages
/home8/venicetw/.local/lib/python/site-packages
/home8/venicetw/public_html/venicenoise/python
/usr/lib64/python24.zip
/usr/lib64/python2.4
/usr/lib64/python2.4/plat-linux2
/usr/lib64/python2.4/lib-tk
/usr/lib64/python2.4/lib-dynload
/usr/lib64/python2.4/site-packages
/usr/lib64/python2.4/site-packages/Numeric
/usr/lib64/python2.4/site-packages/PIL
/usr/lib64/python2.4/site-packages/gtk-2.0
/usr/lib/python2.4/site-packages
但Apache只打印了这些Python路径:
/home8/venicetw/public_html/venicenoise/python
/usr/lib64/python24.zip
/usr/lib64/python2.4
/usr/lib64/python2.4/plat-linux2
/usr/lib64/python2.4/lib-tk
/usr/lib64/python2.4/lib-dynload
/usr/lib64/python2.4/site-packages
/usr/lib64/python2.4/site-packages/Numeric
/usr/lib64/python2.4/site-packages/PIL
/usr/lib64/python2.4/site-packages/gtk-2.0
/usr/lib/python2.4/site-packages
解决方案:通过在PHP和SSH中执行/usr/bin/env,我发现PHP缺少一个环境变量,这个变量是numpy安装的Python路径。在这种情况下,通过在PHP脚本的开头添加
putenv('PYTHONPATH=/home8/venicetw/.local/lib/python2.4/site-packages:/home8/venicetw/.local/lib/python/site-packages:');
一切就按预期工作了。
1 个回答
如果PHP返回的状态是1,这意味着你运行的程序遇到了错误。通常在Unix系统中,非零的退出状态表示出错(不过有些程序是例外,比如diff
)。你可以查看子进程产生的stderr
,看看那里面打印了什么错误信息。
你可以这样显示stderr
:
Output from exec('python hello-numpy.py'):
<?php echo exec('python hello-numpy.py 2>&1'); ?><br>
这里的2>&1
是告诉命令行把stderr
和stdout
合并成一个输出流。通常情况下,你不想这样做,但这样可以更方便地看到错误信息。
更新:你遇到的错误是ImportError: No module named numpy
,我们可以试着查看一下Python的路径。你的系统上可能安装了多个Python版本,也可能Apache的环境(比如根目录等)和你通过SSH运行Python时的环境不同。试着在这两种环境中执行这个Python脚本:
import sys, os
for path in sys.path:
print path
print
print 'Root:', os.readlink('/proc/self/root') # Linux only
其中一个路径应该指向numpy
的安装位置,也许在Apache中运行时这个路径是缺失的。或者Apache进程的根目录不同,这样Python进程就会继承这个不同的根目录。
解决方案:缺少环境变量。请查看评论。