Запуск python-скрипта в WordPress

27 окт. 2013 г., 15:02:08
Просмотры: 111K
Голосов: 22

У меня есть установленный WordPress для личного блога, и я постепенно переношу все свои веб-разработки, написанные за эти годы, на страницы блога.

Одна из таких страниц - http://www.projecttoomanycooks.co.uk/cgi-bin/memory/majorAnalysis.py, которая представляет собой простой python-скрипт, возвращающий список слов. Я хотел бы встроить это поведение в страницу WordPress - не могли бы вы подсказать самый простой способ запуска Python в WordPress?

РЕДАКТИРОВАНИЕ - следуя замечательному ответу ниже, я продвинулся намного дальше... но, к сожалению, все еще не совсем достиг цели...

У меня есть Python, который выполняется на сервере...

projecttoomanycooks server [~/public_html/joereddington/wp-content/plugins]#./hello.py 
Hello World!

и он находится в том же каталоге, что и активированный плагин...

Python-код... который содержит следующее...

#!/usr/bin/python
print("Hello World!")

PHP код:

<?php
/**
 * Plugin Name: Joe's python thing.
 * Plugin URI: http://URI_Of_Page_Describing_Plugin_and_Updates
 * Description: A brief description of the Plugin.
 * Version: The Plugin's Version Number, e.g.: 1.0
 * Author: Name Of The Plugin Author
 * Author URI: http://URI_Of_The_Plugin_Author
 * License: A "Slug" license name e.g. GPL2
 */
/*from 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
Комментарии

Если это очень простой скрипт, я думаю, я бы просто переписал его на PHP в виде плагина/шаблона WordPress ;-) Но в некоторых случаях люди используют iframe для встраивания внешних страниц.

birgire birgire
27 окт. 2013 г. 15:29:19

Встроить напрямую через iframe? :]

Jesse Jesse
27 окт. 2013 г. 15:36:22

Это случайность или ваш код на Python действительно перемешан с PHP?

fuxia fuxia
5 нояб. 2013 г. 19:01:51

Я вставил вывод терминала, где файлы отображаются командой 'more'... немного приведу в порядок...

Joe Joe
5 нояб. 2013 г. 23:42:49
Все ответы на вопрос 3
7
26

Вы можете использовать popen() для чтения или записи в Python-скрипт (это работает и с другими языками). Если вам нужно взаимодействие (передача переменных), используйте proc_open().

Простой пример для вывода Hello World! в плагине WordPress

Создайте плагин и зарегистрируйте шорткод:

<?php # -*- coding: utf-8 -*-
/* Plugin Name: Встроенный Python */

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

Теперь вы можете использовать этот шорткод в редакторе записей с помощью [python] или [python file="filename.py"].

Поместите Python-скрипты, которые хотите использовать, в ту же директорию, где находится файл плагина. Вы также можете поместить их в отдельную папку и изменить путь в обработчике шорткода.

Теперь создайте простой Python-скрипт:

print("Hello World!")

И всё готово. Используйте шорткод и получите такой вывод:

Вывод Hello World в WordPress

27 окт. 2013 г. 15:45:28
Комментарии

Правильный ответ упускает, что первая строка python-скрипта, по крайней мере в моем случае, должна быть #!/usr/bin/env python

MikeiLL MikeiLL
20 мая 2014 г. 02:28:55

@MikeiLL Это зависит от системы пользователя, поэтому я намеренно это опустил.

fuxia fuxia
20 мая 2014 г. 09:33:33

По сути, это создает уязвимость. Если можно передавать данные в python через пайп, то можно передавать и в любой другой процесс, что может быть использовано для эскалации более тривиальных эксплоитов.

Mark Kaplun Mark Kaplun
15 авг. 2018 г. 08:13:28

@MarkKaplun да, это не очень хорошая идея. Чтобы сделать это "правильно", потребуется экранирование команд на входе, а также экранирование в JavaScript и PHP. Это не лучший способ разработки внутри WordPress, если только нет ОЧЕНЬ веской причины для этого. "Ваши -учёные- программисты были так увлечены вопросом, смогут ли они это сделать, что не подумали, следует ли им это делать."

Brian Stinar Brian Stinar
21 янв. 2020 г. 00:15:03

Привет @MarkKaplun, возможно, это связано с моим недостаточным пониманием PHP и WordPress. Я понимаю, что как только появляется возможность передавать произвольные команды в Python, то можно выполнять произвольные команды на хосте от имени пользователя, под которым запущен процесс Python. Но в данном примере происходит только чтение из канала, поэтому я не вижу, как этот плагин можно использовать для записи в канал. Кроме того, только те, кто может изменять страницы WordPress, могут эксплуатировать эту уязвимость, поэтому для личного сайта на WordPress такое решение может быть приемлемым.

Maarten Derickx Maarten Derickx
26 сент. 2020 г. 14:21:51

@M.D., во-первых, необходимо разрешить выполнение команд из PHP, и в зависимости от версии PHP и веб-сервера это может быть возможно только в глобальных настройках, что означает, что любой PHP-скрипт сможет выполнять любые команды в системе. Со стороны Python любой скрипт может выполнять его и использовать любые уязвимости в его безопасности. Возможно, это не так критично, если только вы контролируете сервер и устанавливаете только проверенный код, но даже если люди делают первое, 99.99% сайтов на WordPress не делают второго, поэтому лучше избегать этого, так как никто не может быть уверен, что всегда будет следовать второму правилу.

Mark Kaplun Mark Kaplun
26 сент. 2020 г. 22:40:00

Правильный способ обмена данными между Python и WordPress — это настроить cron в Python, чтобы он запрашивал у WordPress необходимую информацию. Таким образом, вы обеспечиваете безопасность PHP-части. Также важно убедиться, что запросы отправляет именно Python, но это уже более простая задача. Однако такой асинхронный обмен данными не решает вопрос, который задал автор.

Mark Kaplun Mark Kaplun
26 сент. 2020 г. 22:46:28
Показать остальные 2 комментариев
2

Я следовал примеру скрипта из первого ответа, но не получал никакого вывода или ошибок.

Я изменил эту строку:

$handle = popen( __DIR__ . '/' . $data['file'], 'r' );

на эту:

$handle = popen( __DIR__ . '/' . $data['file'] . ' 2>&1', 'r' );

и затем получил сообщение "permission denied" (отказано в доступе).

В консоли я выполнил команду:

chmod 777 hello.py

обновил страницу, и всё заработало идеально.

Возможно, это была проблема, с которой столкнулся Джо выше. У меня недостаточно репутации, чтобы оставить комментарий, извините. Надеюсь, это поможет кому-то.

6 окт. 2016 г. 03:14:38
Комментарии

Не устанавливайте права 777. Просто сделайте файл исполняемым. chmod +x filename.py будет достаточно

Trect Trect
25 июн. 2019 г. 08:36:00

Установка прав 777 для всего очень опасна. Источник: https://superuser.com/questions/1034079/is-it-safe-to-chmod-777-everything

ajinzrathod ajinzrathod
6 мая 2021 г. 18:16:54
0

Вот небольшой скрипт, который использует proc_open, как упоминалось выше, для передачи одной простой текстовой переменной в 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] ); //Чтение буфера stdout
    fclose ( $pipes [1] ); //Закрытие буфера stdout
    fclose ( $pipes [2] ); //Закрытие буфера 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 основная/шорткод функция

Добавлено несколько тестов в конце, чтобы проверить, имеет ли Python-файл права rwx. Я думаю, что лучшим способом передачи argv было бы использование fwrite, но у меня не получилось следовать этому руководству.

Вот Python-скрипт, который я использовал. Как упоминалось в комментариях выше, что-то вроде #!/usr/bin/env python может быть необходимо, в зависимости от сервера.

#!/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 мая 2014 г. 02:28:55