使用 php 读取 python 程序的实时输出

Reading live output of a python program using php

我正在制作一个执行 python 程序的 PHP 网页,当 python 程序正在 运行ning 时,它会实时显示输出. 在遵循 this answer 之后,这是我正在尝试的代码。

$cmd = 'python execs/reduction_code.py';
while(@ ob_end_flush());

$proc = popen($cmd, 'r');
echo '<pre class="box">';

while(!feof($proc)){
    echo fread($proc, 4096);
    @ flush();
}

echo '</pre>';
pclose($proc);

在我开始执行程序reduction_code.py后,每隔30秒,它会显示一些打印语句(说明程序的状态)。该程序大约需要 25 分钟才能完全执行。当我 运行 使用终端的 python 程序时,这很有效。

然而,当我 运行 使用上述 php 代码时,它根本不显示任何输出。文件reduction_code.py是可执行文件,apache有执行和读取的权限。

此外,当我 运行 一个简单的 python 程序通过将 $cmd 中的值替换为 $cmd = 'python execs/test.py'; 来 ping 地址时,我得到了预期的实时我页面中 ping 探测器的输出。

test.py 是:

from subprocess import call
call(["ping", "-c", "10", "localhost"])

我是PHP的新手,我不知道为什么在运行宁reduction.py之后,页面根本没有显示输出。

编辑 1:当我使用 $proc = popen($cmd.' 2>&1', 'r'); 而不是 $proc = popen($cmd, 'r'); 来访问 shell 返回的任何错误消息时。我在我的网页上打印了这条错误消息(在输出应该出现的地方)。

Resource id #9/usr/lib/python2.7/site-packages/IPython/utils/path.py:296: UserWarning: IPython parent '/root' is not a writable location, using a temp directory." using a temp directory."%parent)

/usr/lib64/python2.7/site-packages/astropy/config/configuration.py:687: ConfigurationMissingWarning: Configuration defaults will be used due to OSError:13 on None warn(ConfigurationMissingWarning(msg))
Traceback (most recent call last):
  File "execs/reduction_code.py", line 8, in 
    import matplotlib.pyplot as plt
  File "/usr/lib64/python2.7/site-packages/matplotlib/pyplot.py", line 26, in 
    from matplotlib.figure import Figure, figaspect
  File "/usr/lib64/python2.7/site-packages/matplotlib/figure.py", line 24, in 
    import matplotlib.artist as martist
  File "/usr/lib64/python2.7/site-packages/matplotlib/artist.py", line 7, in 
    from transforms import Bbox, IdentityTransform, TransformedBbox, \
  File "/usr/lib64/python2.7/site-packages/matplotlib/transforms.py", line 35, in 
    from matplotlib._path import (affine_transform, count_bboxes_overlapping_bbox,
ImportError: /opt/lampp/lib/libstdc++.so.6: version `GLIBCXX_3.4.9' not found (required by /usr/lib64/python2.7/site-packages/matplotlib/_path.so)

听起来您需要使 Python 的输出无缓冲 - 当从命令行 运行 时默认情况下是打开的,但在其他情况下是关闭的。解决此问题的最简单方法是在脚本开头将 -u 参数添加到 hashbang:

#!/usr/bin/python -u

我找到了问题的答案。正如输出最后一行中报告的错误:

ImportError: /opt/lampp/lib/libstdc++.so.6: version `GLIBCXX_3.4.9' not found (required by /usr/lib64/python2.7/site-packages/matplotlib/_path.so)

我发现 here lampp 使用的库太旧并且没有定义 GLIBCXX_3.4.9。因此,起初我将 /opt/lampp/lib/libstdc++.so.6 重命名为 /opt/lampp/lib/libstdc++.so.6.orig,然后通过更改命令来更改 LD_LIBRARY_PATH:

$proc = popen($cmd.' 2>&1', 'r');

对此:

$proc = popen("LD_LIBRARY_PATH=/usr/lib/ ".$cmd.' 2>&1', 'r');

我 运行 我的程序经过此更改后,生成了另一份报告,其中说

Runtime Error: could not open display

查了下here and here发现是matplotlib库的问题。我了解到 matplotlib 库默认使用 X-using 后端。并且使用 X 的后端在服务器很少的情况下存在问题。所以我按照答案将这两行插入到我的 reduction_code.py 程序

import matplotlib
matplotlib.use('Agg')

现在,一切都按预期进行。谢谢支持