Estoy creando una página web PHP que ejecuta un programa python y, mientras se ejecuta el programa python, muestra el resultado en tiempo real. Después de seguir esta respuesta , este es el código que estoy intentando.
$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); Después de comenzar a reduction_code.py el programaduction_code.py, cada 30 segundos, muestra algunas declaraciones de impresión (que informan sobre el estado del programa). El programa tarda aproximadamente 25 minutos en ejecutarse por completo. Esto funciona bien cuando ejecuto el programa python usando la terminal.
Sin embargo, cuando ejecuto esto usando el código php anterior, no muestra ningún resultado. El reduction_code.py es ejecutable y apache tiene permiso para ejecutarlo y leerlo.
Además, cuando ejecuto un programa python simple para hacer ping a una dirección reemplazando el valor en $cmd como $cmd = 'python execs/test.py'; , obtengo la salida esperada en tiempo real de las sondas de ping en mi página.
test.py es:
from subprocess import call call(["ping", "-c", "10", "localhost"]) Soy nuevo en PHP y no tengo idea de por qué después de ejecutar la reduction.py , la página no muestra ningún resultado.
EDITAR 1 : Cuando uso $proc = popen($cmd.' 2>&1', 'r'); en lugar de $proc = popen($cmd, 'r'); para acceder a cualquier mensaje de error devuelto por shell. Recibo este mensaje de error impreso en mi página web (en el lugar donde se esperaba que apareciera la salida).
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)Parece que necesita hacer que la salida de Python no tenga búfer; esto está activado de forma predeterminada cuando se ejecuta desde la línea de comando, pero de lo contrario está desactivado. La forma más fácil de solucionar esto es agregar el argumento -u al hashbang al comienzo del script:
#!/usr/bin/python -u
Encontré respuesta a mi pregunta. Como error informado en la última línea de la salida:
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) Descubrí aquí que las bibliotecas que usa lampp son demasiado antiguas y no definen GLIBCXX_3.4.9 . Entonces, al principio cambié el nombre de /opt/lampp/lib/libstdc++.so.6 a /opt/lampp/lib/libstdc++.so.6.orig y luego cambié LD_LIBRARY_PATH cambiando el comando de este:
$proc = popen($cmd.' 2>&1', 'r');a esto:
$proc = popen("LD_LIBRARY_PATH=/usr/lib/ ".$cmd.' 2>&1', 'r');Después de ejecutar mi programa después de este cambio, se generó otro informe que decía que
Runtime Error: could not open display Después de buscar un poco, encontré aquí y aquí que era el problema de la biblioteca matplotlib . Aprendí que la biblioteca matplotlib usa el backend X-using de forma predeterminada. Y el backend que usa X tiene problemas con pocos servidores. Así que seguí la respuesta e reduction_code.py estas dos líneas en mi programaduction_code.py
import matplotlib matplotlib.use('Agg')Y ahora, todo está funcionando como se esperaba. Gracias por su apoyo.