Ejecutar un script de Python dentro de WordPress
Tengo una instalación de WordPress para un blog personal y estoy migrando gradualmente todos los pequeños fragmentos web que he escrito a lo largo de los años a páginas del blog.
Una de esas páginas es http://www.projecttoomanycooks.co.uk/cgi-bin/memory/majorAnalysis.py, que es un simple script de Python que devuelve una lista de palabras - me gustaría integrar ese comportamiento dentro de una página de WordPress - ¿alguien podría indicarme la forma más sencilla de ejecutar un poco de Python dentro de WordPress?
EDICIÓN - siguiendo la maravillosa respuesta de abajo, he avanzado mucho... pero desafortunadamente aún no he llegado del todo...
Tengo Python que se ejecuta en el servidor...
projecttoomanycooks server [~/public_html/joereddington/wp-content/plugins]#./hello.py
Hello World!
y está en el mismo directorio que el plugin activado...
El código Python... que tiene el siguiente contenido...
#!/usr/bin/python
print("Hello World!")
El PHP:
<?php
/**
* Nombre del Plugin: Plugin de Python de Joe.
* URI del Plugin: http://URI_De_La_Pagina_Que_Describe_El_Plugin_y_Actualizaciones
* Descripción: Una breve descripción del Plugin.
* Versión: Número de Versión del Plugin, ej.: 1.0
* Autor: Nombre Del Autor Del Plugin
* URI del Autor: http://URI_Del_Autor_Del_Plugin
* Licencia: Un nombre de licencia "Slug" ej. GPL2
*/
/*de http://wordpress.stackexchange.com/questions/120259/running-a-python-scri
pt-within-wordpress/120261?noredirect=1#120261 */
add_shortcode( 'python', 'embed_python' );
function embed_python( $attributes )
{
$data = shortcode_atts(
array(
'file' => 'hello.py'
),
$attributes
);
$handle = popen( __DIR__ . '/' . $data['file'], 'r');
$read = fread($handle, 2096);
pclose($handle);
return $read;
}

Puedes usar popen()
para leer o escribir en un script de Python (esto funciona con cualquier otro lenguaje también). Si necesitas interacción (pasar variables) usa proc_open()
.
Un ejemplo simple para imprimir ¡Hola Mundo! en un plugin de WordPress
Crea el plugin, registra un shortcode:
<?php # -*- coding: utf-8 -*-
/* Plugin Name: Python integrado */
add_shortcode( 'python', 'embed_python' );
function embed_python( $attributes )
{
$data = shortcode_atts(
[
'file' => 'hello.py'
],
$attributes
);
$handle = popen( __DIR__ . '/' . $data['file'], 'r' );
$read = '';
while ( ! feof( $handle ) )
{
$read .= fread( $handle, 2096 );
}
pclose( $handle );
return $read;
}
Ahora puedes usar ese shortcode en el editor de entradas con [python]
o [python file="nombre_archivo.py"]
.
Coloca los scripts de Python que quieras usar en el mismo directorio que el archivo del plugin. También puedes colocarlos en un directorio y ajustar la ruta en el manejador del shortcode.
Ahora crea un script complejo de Python como este:
print("¡Hola Mundo!")
Y eso es todo. Usa el shortcode y obtendrás esta salida:

La respuesta correcta omite que la primera línea del script de Python, al menos en mi caso, necesita ser #!/usr/bin/env python

@MikeiLL Eso depende del sistema del usuario, así que lo omití deliberadamente.

básicamente creando un agujero de seguridad. Si puedes redirigir a Python, también puedes redirigir a cualquier otro proceso y esto puede usarse para escalar cualquier explotación más trivial.

@MarkKaplun sí, esta no es una buena idea. Para hacer esto "correctamente" tendría que haber escape de comandos en la entrada, y escape de JavaScript+PHP en la salida. Esta no es una buena forma de desarrollar nada dentro de WordPress, a menos que haya una razón MUY específica para hacerlo. "Tus -científicos- programadores estaban tan preocupados por si podían hacerlo, que no se detuvieron a pensar si deberían hacerlo."

Hola @MarkKaplun, podría ser mi falta de comprensión de PHP y WordPress. Entiendo que tan pronto como puedas enviar comandos arbitrarios a Python, entonces podrás ejecutar comandos arbitrarios en el host como el usuario bajo el cual se ejecuta el proceso de Python. Pero en este ejemplo solo se está realizando una lectura desde la tubería, por lo que no veo cómo este plugin puede usarse para escribir en la tubería. Además, solo las personas que pueden modificar páginas de WordPress pueden explotar este agujero de seguridad, por lo que podría ser una solución aceptable para un sitio WordPress personal.

@M.D., primero necesitas habilitar la ejecución fuera de PHP, y dependiendo de la versión de PHP y el servidor web, podrías hacerlo solo como una configuración global, lo que significa que cualquier script PHP puede ejecutar todo en el sistema. Desde el lado de Python, cualquier script puede ejecutarlo y explotar cualquier problema de seguridad que tenga. Esto podría no ser gran cosa si solo tú tienes control del servidor y solo se instala código verificado, pero incluso si las personas hacen lo primero, el 99.99% de los sitios de WordPress no hacen lo segundo, por lo que es mejor evitarlo, ya que nadie puede confíar en sí mismo para seguir lo segundo todo el tiempo.

la forma correcta de comunicarse entre Python y WordPress es configurar un cron en Python y hacer que consulte a WordPress para obtener cualquier información que pueda necesitar. De esta manera mantienes el lado de PHP seguro. Aún necesitas asegurarte de que sea Python el que solicita la información, pero esto es algo más trivial de hacer. Sin embargo, este tipo de comunicación asíncrona no resolverá la pregunta como el OP preguntó.

Seguí el script de ejemplo de la primera respuesta, pero no obtenía ninguna salida ni errores.
Cambié esta línea:
$handle = popen( __DIR__ . '/' . $data['file'], 'r' );
por esta:
$handle = popen( __DIR__ . '/' . $data['file'] . ' 2>&1', 'r' );
y entonces obtuve un mensaje de "permiso denegado".
En la consola, ejecuté
chmod 777 hello.py
actualicé la página y todo funcionó perfectamente.
Este podría ser el problema que Joe estaba experimentando arriba. No tengo suficiente reputación para hacer un comentario, lo siento. Espero que esto ayude a alguien.

No establezcas el permiso en 777. Solo hazlo ejecutable. chmod +x archivo.py
será suficiente

Cambiar todo a 777 es muy peligroso. Fuente: https://superuser.com/questions/1034079/is-it-safe-to-chmod-777-everything

Aquí hay un pequeño script que utiliza proc_open
como se mencionó anteriormente, para enviar una variable de texto simple a un script de Python:
add_shortcode( 'execute_python', 'execute_python_with_argv' );
function execute_python_with_argv( $attributes ){
$description = array (
0 => array("pipe", "r"), // stdin
1 => array("pipe", "w"), // stdout
2 => array("pipe", "w") // stderr
);
$application_system = "python ";
$application_path .= plugin_dir_path( __FILE__ );
$application_name .= "hello.py";
$separator = " ";
$application = $application_system.$application_path.$application_name.$separator;
$argv1 = '"output to receive back from python script"';
$pipes = array();
$proc = proc_open ( $application.$argv1 , $description , $pipes );
//echo proc_get_status($proc)['pid'];
if (is_resource ( $proc ))
{
echo "Stdout : " . stream_get_contents ( $pipes [1] ); //Leyendo buffer stdout
fclose ( $pipes [1] ); //Cerrando buffer stdout
fclose ( $pipes [2] ); //Cerrando buffer stderr
$return_value = proc_close($proc);
echo "<br/>command returned: $return_value<br/>";
}
$application_test = glitch_player_DIR.$application_name;
echo "<br/>Is ".$application_test." executable? ".is_executable($application_test)." ";
echo "readable? ".is_readable($application_test)." ";
echo "writable? ".is_writable($application_test)." ";
} //EOF función principal/shortcode
Agregué algunas pruebas al final para ver si el archivo de Python tiene permisos rwx
. Creo que una mejor manera de enviar el argv
sería usando fwrite, pero no funcionó para mí siguiendo este tutorial.
Aquí está el script de Python que usé. Como se menciona en los comentarios anteriores, algo como #!/usr/bin/env python
puede ser necesario, dependiendo del servidor.
#!/usr/bin/env python
from sys import argv
script, what_he_said = argv
print "This is what you submitted: %s \n \n Isn't that amazing, man? " % what_he_said
