Передача объекта массива из PHP в Python

Это мой код до сих пор

    $dataraw = $_SESSION['image'];
    $datagambar = json_encode($dataraw);

    echo '<pre>';
    print_r($dataraw);
    echo '</pre>';

    print($escaped_json);

    $type1 = gettype($dataraw);
    print($type1);

    $type2 = gettype($datagambar);
    print($type2);

Это вывод $dataraw, тип — массив

Array
(
    [0] => Array
        (
            [FileName] => 20221227_202035.jpg
            [Model] => SM-A528B
            [Longitude] => 106.904251
            [Latitude] => -6.167665
        )

    [1] => Array
        (
            [FileName] => 20221227_202157.jpg
            [Model] => SM-A528B
            [Longitude] => 106.9042428
            [Latitude] => -6.1676580997222
        )

)

Это вывод $datagambar, тип строки

[{"FileName":"20221227_202035.jpg","Model":"SM-A528B","Longitude":106.904251,"Latitude":-6.167665},{"FileName":"20221227_202157.jpg","Model":"SM-A528B","Longitude":106.9042428,"Latitude":-6.167658099722223}]

Перейти на питон

echo shell_exec("D:\Anaconda\python.exe D:/xampp/htdocs/Klasifikasi_KNN/admin/test.py $datagambar");

Это мой Python test.py

import sys, json
import os
import pymysql
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import mplcursors as mpl
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score,hamming_loss,classification_report

json_list = []
escaped_json1 = sys.argv[1]

# this is working but its only a string of array json
# print(escaped_json1) 
# this is working but its only a string of array json

json_list.append(json.loads(escaped_json1))
parsed_data = json.loads(escaped_json1) 
print(json_list)
print(parsed_data)

Когда я печатаю (escaped_json1), он отображает строку массива json из php ($ datagambar).

Вывод питона:

Hello world has been called [{"FileName":"20221227_202035.jpg","Model":"SM-A528B","Longitude":106.904251,"Latitude":-6.167665},{"FileName":"20221227_202157.jpg","Model":"SM-A528B","Longitude":106.9042428,"Latitude":-6.167658099722223}]

Я использую apache в качестве своего сервера с phpmyadmin и anaconda.

T пытался использовать print(type(escapedjson1)) или print(type(escapedjson1)) но не отображает тип

Json.loads не изменил тип данных на массив python

Как загрузить его и превратить массив строк в массив переменных, чтобы я мог вызвать его и преобразовать в фрейм данных?

Возможно, оболочка не интерпретирует значение переменной $datagambar как отдельный аргумент, поэтому вы можете увидеть некоторый вывод при печати, но не можете проанализировать, поскольку он может быть недопустимым JSON, вы можете попробовать обернуть переменную в одиночный цитаты: echo shell_exec("D:\Anaconda\python.exe D:/xampp/htdocs/Klasifikasi_KNN/admin/test.py '$datagambar'");

RJK 10.01.2023 17:51

Нет, экранирование аргументов не работает, просто заключая их в одинарные кавычки, @RJK. Вы должны сделать это правильно, иначе вы рискуете внедрить код. На самом деле, я бы предпочел такой интерфейс, как pcntl_exec(), где вы не ставите оболочку посередине, но, боюсь, эта функция только для POSIX.

Ulrich Eckhardt 10.01.2023 21:53

Можете ли вы поделиться результатом print(type(escaped_json1))

executable 11.01.2023 12:20

@executable ничего не распечатал

Jessen Jie 12.01.2023 05:59

Вы должны просто использовать временный файл для передачи ваших данных.

Olivier 13.01.2023 20:53
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Библиотека для работы с мороженым
Библиотека для работы с мороженым
Лично я попрощался с операторами print() в python. Без шуток.
Эмиссия счетов-фактур с помощью Telegram - Python RPA (BotCity)
Эмиссия счетов-фактур с помощью Telegram - Python RPA (BotCity)
Привет, люди RPA, это снова я и я несу подарки! В очередном моем приключении о том, как создавать ботов для облегчения рутины. Вот, думаю, стоит...
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Шаг 1: Создание приложения Slack Чтобы создать Slackbot, вам необходимо создать приложение Slack. Войдите в свою учетную запись Slack и перейдите на...
Учебник по веб-скрапингу
Учебник по веб-скрапингу
Привет, ребята... В этот раз мы поговорим о веб-скрейпинге. Целью этого обсуждения будет узнать и понять, что такое веб-скрейпинг, а также узнать, как...
Тонкая настройка GPT-3 с помощью Anaconda
Тонкая настройка GPT-3 с помощью Anaconda
Зарегистрируйте аккаунт Open ai, а затем получите ключ API ниже.
4
5
253
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вам просто нужно заключить в одинарные кавычки аргумент для python:

Shell_exec("python3 test.py '$json'");

Пример

Файл.php

$data =
[
    [
        "FileName" => "20221227_202035.jpg",
        "Model" => "27_202035.jpg",
        "Longitude" => 106.90425,
        "Latitude" => 106.90425
    ],
    [
        "FileName" => "20221227_202157.jpg",
        "Model" => "SM-A528B",
        "Longitude" => 106.9042428,
        "Latitude" => -6.1676580997222
    ]
];

$json = json_encode($data);

// note: arg '$json' is single-quoted
echo shell_exec("python3 test.py '$json'");

Test.py

import sys
import json
from pandas import json_normalize

data = sys.argv[1]

dict = json.loads(data)
df2 = json_normalize(dict) 

print(df2)

Выход

              FileName     Model   Longitude  Latitude
0  20221227_202035.jpg  SM-A528B  106.904251 -6.167665
1  20221227_202157.jpg  SM-A528B  106.904243 -6.167658

Видеть: Экранирование двойных кавычек при отправке JSON в качестве аргумента в программе на Python

Кало спасибо за ответ. он не запускал файл python, если я импортировал из pandas.io.json import json_normalize

Jessen Jie 13.01.2023 13:42

В file.php ваша переменная $json представляет собой строку, а не массив, как в фактическом вводе, который должен обрабатывать OP.

Booboo 13.01.2023 14:37

@Booboo да, это строка массива json, потому что оболочка exec из php не может явно передать массив в python. Если я передам сам $dataraw и не закодирую его сначала в $datagambar, я получу предупреждение: преобразование массива в строку

Jessen Jie 13.01.2023 14:51

@calogero Ваш вывод - это то, что я ищу ... я запускаю свой php с сервером apache phpMyAdmin. Когда я пытаюсь импортировать панды только без их использования или делать что-либо еще, php не выполняет файл python с помощью shell_exec..

Jessen Jie 13.01.2023 15:01

@JessenJie Вы используете свою строку вместо моей («python3 test.py $json»)?

calogero 13.01.2023 15:11

@calogero, я тоже пробовал ваши строки, они работают так же, как $datagambar.

Jessen Jie 13.01.2023 15:35

@calogero json.loads выполняется и может быть распечатан, но вывод по-прежнему представляет собой строки json .. я думаю? потому что я не могу проверить тип с помощью print(type(data))

Jessen Jie 13.01.2023 15:50
print(type(dict)) дает <class 'list'> мне
calogero 13.01.2023 16:01

Давайте продолжим обсуждение в чате.

calogero 13.01.2023 16:02

Как сказал @Booboo, начальный ввод - это массив. Я отредактировал свой ответ, чтобы отразить это. Я надеюсь, что это может помочь.

calogero 13.01.2023 21:42

«Вам просто нужно заключить в одинарные кавычки». Вы тестировали это в Windows? А что произойдет, если строка JSON будет содержать одинарные кавычки?

Olivier 14.01.2023 09:57
Ответ принят как подходящий

Обновление: совершенно другой подход

Существует проблема с JSON-кодированием PHP-скрипта структуры для создания строки JSON и последующей передачей ее в качестве аргумента командной строки, поскольку строку необходимо поместить в двойные кавычки, поскольку в закодированной строке могут быть встроенные пробелы. Но сама строка может содержать двойные кавычки в качестве начала строковых символов и внутри такой строки. Смущенный? Кто бы не был?

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

Предположим, ваш массив выглядит так:

$arr =
[
    [
        "FileName" => "\"\\  \nRon's20221227_202035.jpg",
        "Model" => "27_202035.jpg",
        "Longitude" => 106.90425,
        "Latitude" => 106.90425
    ],
    [
        "FileName" => "20221227_202157.jpg",
        "Model" => "SM-A528B",
        "Longitude" => 106.9042428,
        "Latitude" => -6.1676580997222
    ]
];

Обратите внимание, что я немного изменил ваш пример, так что первое поле FileName содержит символ ", символ ', escape-последовательность \n, представляющую символ новой строки, и, наконец, несколько пробелов. Хотя ваш пример не содержит этих символов или какой-либо другой escape-последовательности, я хотел бы иметь возможность обрабатывать такое условие, если оно возникнет. Это решение должно работать с таким вводом.

PHP-файл

<?php
$arr =
[
    [
        "FileName" => "\"\\  \nRon's20221227_202035.jpg",
        "Model" => "27_202035.jpg",
        "Longitude" => 106.90425,
        "Latitude" => 106.90425
    ],
    [
        "FileName" => "20221227_202157.jpg",
        "Model" => "SM-A528B",
        "Longitude" => 106.9042428,
        "Latitude" => -6.1676580997222
    ]
];

// Encode string as JSON:
$json = json_encode($arr);

// Pipe the JSON string to the Python process's stdin and
// read the result from its stdout:
$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
   1 => array("pipe", "w")   // stdout is a pipe that the child will write to
);
$options = array('bypass_shell' => True); // Only has effect on Windows
//$process = proc_open("python3 test.py", $descriptorspec, $pipes, null, null, $options);
// For your actual environment:
$process = proc_open("D:/Anaconda/python.exe D:/xampp/htdocs/Klasifikasi_KNN/admin/test.py", $descriptorspec, $pipes, null, null, $options);

// Pipe the input for the Python program and close the pipe:
fwrite($pipes[0], $json);
fclose($pipes[0]);

// Read the result from the Python program and close its pipe
$result = stream_get_contents($pipes[1]);
fclose($pipes[1]);

# Now that we have closed the pipes, we can close the process:
$return_code = proc_close($process);

echo "Result from stdin:\n$result\n";

Test.py

import json
import sys

DEBUG = True # for debugging purposes

if DEBUG:
    import os

    for k, v in sorted(os.environ.items()):
        print(k, '->', v, file=sys.stderr)
else:
    import numpy as np
    import pandas as pd

# Load from stdin:
arr = json.load(sys.stdin)
# print each dictionary of the array:
for d in arr:
    print(d)

Отпечатки:

{'FileName': '"\\  \nRon\'s20221227_202035.jpg', 'Model': '27_202035.jpg', 'Longitude': 106.90425, 'Latitude': 106.90425}
{'FileName': '20221227_202157.jpg', 'Model': 'SM-A528B', 'Longitude': 106.9042428, 'Latitude': -6.1676580997222}

Спасибо за ответ. Я все еще изучаю ваш ответ, вы создаете формат, который может работать с json.loads? можно ли изменить мой массив на ваш?

Jessen Jie 13.01.2023 17:28

См. мой файл Python выше; он делает json.loads() против переданного аргумента программе. Программа сначала выводит переданный аргумент, который является строкой, затем выводит результат выполнения json.loads() для этой строки, которая является списком Python, и, наконец, код выводит каждый элемент списка, который является словарем Python. Каждая из этих трех операций печати разделена пунктирной линией (см. вывод выше).

Booboo 13.01.2023 19:18

«может быть упрощено путем двойного кодирования массива». Вы не должны использовать json_encode() в строке, чтобы избежать ее. Бывает, что работает, но это просто случайность. Он не для этого предназначен.

Olivier 13.01.2023 20:47

@Olivier Смотрите обновленный код; это совершенно другой и более надежный подход (во всяком случае, на мой взгляд).

Booboo 13.01.2023 23:17

Файловый подход определенно намного лучше (лично я бы просто использовал временный файл). Вы видели примечание на странице proc_open относительно опции bypass_shell? Его использование выглядит более безопасным.

Olivier 14.01.2023 09:42

@Olivier Это может быть быстрее, но я не понимаю, как в этом случае это безопаснее. Кстати, это вариант только для Windows. Если бы это имело общее применение, то я мог бы увидеть, как это повлияет на то, было ли расширение аргументов с подстановочными знаками выполнено или нет, например, в Linux. Но быстрее - это хорошо.

Booboo 14.01.2023 11:44

@Booboo Сэр, почему, если я импортирую пакеты, отличные от sys и json, php shell_exec не запускает файл python? такие как панды, numpy или matplotlib.

Jessen Jie 15.01.2023 05:51

Я добавил импорт для pandas и numpy, и у меня все еще работало. Для загрузки этих больших пакетов требуется время, поэтому ответ не будет возвращаться так быстро. Вы уверены, что это были единственные изменения, которые вы внесли? Возможно, вам нужно опубликовать, как именно выглядел ваш файл Python.

Booboo 15.01.2023 11:21

Я обновил ответ последним источником Python, показывающим дополнительный импорт. Я также использую json.load() непосредственно против sys.stdin вместо того, чтобы сначала читать ввод, а затем использовать json.loads(). Эти два способа эквивалентны, но теперь это на одну строку короче.

Booboo 15.01.2023 11:52

Вы также можете попробовать запустить python3 test.py из командной строки, а затем ввести [1,2], а затем клавишу ввода, а затем либо Ctrl-Z (Windows), либо Ctrl-D (Linux), чтобы сигнализировать о конце файла. Посмотрите, не выводятся ли какие-либо сообщения об ошибках. Но если вы точно запустите мой код выше, он должен просто распечатать 1 и 2 в отдельных строках.

Booboo 15.01.2023 12:06

Я только что заметил, что вы упомянули shell_exec в своем комментарии. В моем обновленном ответе этот вызов не используется. Пожалуйста, перечитайте мой ответ.

Booboo 15.01.2023 13:20

@Booboo Вы можете проверить это видео, что при импорте пакетов код не запускается drive.google.com/file/d/1nREl3toV6w0b-nXEOTPNkrjg1BtqL44_/…

Jessen Jie 15.01.2023 13:20

Я не могу следить за твоей "демо". Как выглядит ваш PHP-код? Это похоже на мой код выше?

Booboo 15.01.2023 13:22

@Booboo Я скопировал точно так же, как твой код

Jessen Jie 15.01.2023 13:24

Я не знаю, какое у вас окружение. Вы пробовали запустить это из командной строки с помощью python3 test.py, как я изложил несколько комментариев назад?

Booboo 15.01.2023 13:25

Python3 test.py не запускал код Python, я использую базовую среду anaconda. D:\xampp\htdocs\Klasifikasi_KNN>python3 test.py Python не найден; запустить без аргументов для установки из Microsoft Store или отключить этот ярлык в меню «Настройки» > «Управление псевдонимами выполнения приложений». D:\xampp\htdocs\Klasifikasi_KNN>python3 test.py Python не найден; запустить без аргументов для установки из Microsoft Store или отключить этот ярлык в меню «Настройки» > «Управление псевдонимами выполнения приложений».

Jessen Jie 15.01.2023 13:27

Вы не можете запустить программу Anaconda Python из командной строки? И как на это подается входной JSON? В вашей демонстрации запущена программа PHP? Моя просьба выше заключалась в том, чтобы вы вводили [1,2} и т. д. только для программы Python, чтобы мы могли видеть любые сообщения об ошибках. Честно говоря, я понятия не имею, что вы делаете в этом видео.

Booboo 15.01.2023 13:30

Я имею в виду, что вам явно нужно изменить программу PHP, чтобы она указывала на ваш исполняемый файл Python и исходный код Python, чтобы вы кодировали программу PHP: proc_open("D:\Anaconda\python.exe D:/xampp/htdocs/Klasifikasi_KNN/admin/test.py", etc.)

Booboo 15.01.2023 13:38

@Booboo о, да, извините .., прежде чем я изменил его на proc_open("D:\Anaconda\python.exe D:/xampp/htdocs/Klasifikasi_KNN/admin/test.py" и т. д.), потому что раньше с python test.py это не работает

Jessen Jie 15.01.2023 14:03

Давайте продолжим обсуждение в чате.

Jessen Jie 15.01.2023 14:05

Другие вопросы по теме