Ejecutar un script de Python dentro de WordPress

27 oct 2013, 15:02:08
Vistas: 111K
Votos: 22

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;
}
4
Comentarios

Si es un script muy simple, creo que simplemente lo reescribiría en PHP como un plugin/plantilla de WordPress ;-) Pero en algunos casos la gente usa iframes para incrustar páginas externas.

birgire birgire
27 oct 2013 15:29:19

¿Incrustarlo directamente con iframe? :]

Jesse Jesse
27 oct 2013 15:36:22

¿Es solo un accidente o tu código Python realmente está mezclado con PHP?

fuxia fuxia
5 nov 2013 19:01:51

Pegué el rastro de la terminal, con los archivos mostrados por el comando 'more'... lo organizaré un poco...

Joe Joe
5 nov 2013 23:42:49
Todas las respuestas a la pregunta 3
7
26

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:

Descripción de la imagen aquí

27 oct 2013 15:45:28
Comentarios

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 MikeiLL
20 may 2014 02:28:55

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

fuxia fuxia
20 may 2014 09:33:33

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.

Mark Kaplun Mark Kaplun
15 ago 2018 08:13:28

@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."

Brian Stinar Brian Stinar
21 ene 2020 00:15:03

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.

Maarten Derickx Maarten Derickx
26 sept 2020 14:21:51

@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.

Mark Kaplun Mark Kaplun
26 sept 2020 22:40:00

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ó.

Mark Kaplun Mark Kaplun
26 sept 2020 22:46:28
Mostrar los 2 comentarios restantes
2

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.

6 oct 2016 03:14:38
Comentarios

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

Trect Trect
25 jun 2019 08:36:00

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

ajinzrathod ajinzrathod
6 may 2021 18:16:54
0

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
20 may 2014 02:28:55