0

пытаюсь связать python с php, а именно - внедрить нейронные сети в сайт.
вызываю из php скрипт таким образом:

$x = shell_exec("python C:/Users/mx/script.py \"".$_POST["text"]."\" 2>&1");
echo($x);

в script.py написано следующее:

import sys
tx = sys.argv[1]
tx = tx.lower()
print(tx)

в итоге я вижу текст вида �����, но если я уберу строку tx = tx.lower(), то текст вернётся в нужной кодировке, так как я его вписал на странице. любые русские буквы превращаются в знаки вопроса, остальные символы отображаются нормально. при этом непосредственно из cmd всё работает как надо.

можно, конечно, подготовить текст в php, но, думаю, это не совсем правильно.

как получить текст в нормальной кодировке после обработки в python?

и ещё вопрос по поводу сброса вывода, мне в php нужна лишь последняя строка, т.е. непосредственно результат работы сети. я обложился функциями сброса:

sys.stdout.flush()
print(tx, flush=True)
sys.stdout.flush()
sys.exit()

однако всё равно возвращается лишняя строка: Using TensorFlow backend. , причём после вывода print(). как правильно получать от скрипта только нужные данные?

Maximmka
  • 387
  • 7
  • 22
  • Посмотрите в сторону похожей проблемы...

    https://ru.stackoverflow.com/questions/141035/%d0%9a%d0%b0%d0%ba-%d0%b8%d0%b7-python-%d0%b2%d1%8b%d0%b2%d0%b5%d1%81%d1%82%d0%b8-%d0%bd%d0%b0-windows-%d0%ba%d0%be%d0%bd%d1%81%d0%be%d0%bb%d1%8c-%d1%81%d1%82%d1%80%d0%be%d0%ba%d1%83-%d0%b2-%d0%ae%d0%bd%d0%b8%d0%ba%d0%be%d0%b4%d0%b5/359348#359348

    – Tihon May 15 '18 at 13:01
  • что у вас python -V печатает в php окружении? (вы уверены, что именно 3.5?) – jfs May 15 '18 at 16:27
  • 1
    здесь множество движущихся частей, чтобы упростить: замените $_POST["text"] на фиксированную строку к примеру: "\u{430}\u{431}\u{432}". В Питоне добавьте: print(ascii(sys.argv[1])) и print(sys.stdout.encoding) – jfs May 15 '18 at 16:32
  • 1
    про flush=True отдельный Stack Overflow вопрос задайте. – jfs May 15 '18 at 16:34
  • через php python --version отвечает Python 3.5.3.

    print(ascii(sys.argv[1])) печатает \\u{430}\\u{431}\\u{432}.

    print(sys.stdout.encoding) печатает cp1251.

    одинаково и через консоль, и через php.

    – Maximmka May 16 '18 at 07:48
  • ещё заметил что когда tx="текст", len(tx) выдаёт разные результаты: когда выполняю через php - показывает длину строки 10, когда через консоль - показывает 5. при этом кодировку они показали одинаковую, как так получилось? – Maximmka May 16 '18 at 07:52
  • Питон не должен видеть \u буквально. Что у вас: echo "\u{430}\u{431}\u{432}" . phpversion(); показывает? – jfs May 16 '18 at 08:36

1 Answers1

0

разобрался.

cmd работает в cp1251, php в UTF-8.

что бы нормально работало надо перед запуском shell_exec перекодировать текст в cp1251, иначе они будут иметь разную длину (при тестах из php и cmd текст выводился одинаково, однако len(text) показывал 10 для php, и 5 для cmd).

так же, для вывода нам надо перекодировать всё обратно, иначе мы будем видеть те самые �����.

$tx = iconv("UTF-8", "cp1251", $_POST["text"]);
$cmd = "python C:/Users/mx/script.py \"".$tx."\" 2>&1";
$x = shell_exec($cmd);
$x = iconv("cp1251", "UTF-8", $x);
echo($x);

помните что shell_exec потенциально опасная функция, всегда проверяйте то, что вы ей передаёте

Maximmka
  • 387
  • 7
  • 22
  • Это может указывать, что shell_exec() использует ANSI (non-unicode) API на Windows, чтобы запустить команду. ANSI codepage может отличаться от cp1251 (к примеру, cp1252). Использование неверной кодировки может к кракозябрам вести. Это не имеет отношения к кодировке cmd (chcp, OEM codepage, к примеру cp866). Второе преобразование можно убрать, если выставить PYTHONIOENCODING переменную окружения (чтобы можно было принять от python команды вывод, которые не представим в ANSI cp, к примеру, python -c "print(u'\N{SNOWMAN}')") – jfs May 16 '18 at 08:44