【问题标题】:PHP script can't get output from Python scriptPHP 脚本无法从 Python 脚本获取输出
【发布时间】:2012-02-01 00:50:55
【问题描述】:

我在从 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') 的输出:你好,世界!
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,PHP 的返回状态为 0,而 hello-numpy.py 的返回状态为 1。我认为这可能是权限问题,但 PHP 和 SSH 都以“venicetw”用户身份运行。什么会阻止 PHP 和 Apache 从 Python 脚本获取输出?这是我可以与 Bluehost 讨论的事情,还是我应该检查的其他事情?我们正在使用Apache 2.2.21PHP 5.2.17Python 2.4.3numpy 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 路径的环境变量。在这种情况下,通过添加

putenv('PYTHONPATH=/home8/venicetw/.local/lib/python2.4/site-packages:/home8/venicetw/.local/lib/python/site-packages:');

到 PHP 脚本的开头,一切正常。

【问题讨论】:

    标签: php python apache numpy


    【解决方案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&gt;&amp;1 指示 shell 将 stderrstdout 组合成一个流。您通常不想这样做,但它可以很容易地查看错误。

    更新:由于您得到的错误是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 进程继承。

    解决方案:缺少环境变量。见 cmets。

    【讨论】:

    • 啊,得到了这个:"ImportError: No module named numpy" 不知道是不是重启Apache的问题?
    • 确保两次访问的python版本相同。
    • 刚刚检查过 - 他们都在访问 Python 2.4.3。在共享托管环境中,重新启动 Apache 不是一种选择。
    • 如果有帮助,请尝试使用虚拟环境,这样您就可以将 SAME envs 作为丢弃环境作为问题。
    • @Neil:重新启动 Apache(可能)无论如何都无济于事。请参阅编辑后的答案。