使用 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')
现在,一切都按预期进行。谢谢支持
我正在制作一个执行 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')
现在,一切都按预期进行。谢谢支持