I’m trying to run a Python script from a PHP script using proc_open. The Python script works fine when run directly from the command line, but raises a UnicodeEncodeError when run from PHP. I suspect the issue might be related to how the output is captured and handled in PHP, but I’m not sure how to fix it.
I’m working on a project where I need to invoke a Python script from a PHP script. The Python script processes some data and prints the results. Here is the PHP code I’m using:
<code><?php
function my_shell_exec($cmd, &$stdout=null, &$stderr=null) {
$proc = proc_open($cmd,[
1 => ['pipe','w'],
2 => ['pipe','w'],
],$pipes);
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);
return proc_close($proc);
}
$output = my_shell_exec('.\.venv\Scripts\activate && .\.venv\Scripts\python.exe infer.py', $stdout, $stderr);
var_dump($output);
var_dump($stdout);
var_dump($stderr);
exit();
</code>
<code><?php
function my_shell_exec($cmd, &$stdout=null, &$stderr=null) {
$proc = proc_open($cmd,[
1 => ['pipe','w'],
2 => ['pipe','w'],
],$pipes);
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);
return proc_close($proc);
}
$output = my_shell_exec('.\.venv\Scripts\activate && .\.venv\Scripts\python.exe infer.py', $stdout, $stderr);
var_dump($output);
var_dump($stdout);
var_dump($stderr);
exit();
</code>
<?php
function my_shell_exec($cmd, &$stdout=null, &$stderr=null) {
$proc = proc_open($cmd,[
1 => ['pipe','w'],
2 => ['pipe','w'],
],$pipes);
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);
return proc_close($proc);
}
$output = my_shell_exec('.\.venv\Scripts\activate && .\.venv\Scripts\python.exe infer.py', $stdout, $stderr);
var_dump($output);
var_dump($stdout);
var_dump($stderr);
exit();
Output from PHP:
<code>int(1)
string(183) "Init model
Model already exists in keras-model/model-transventricular-v3.keras, skipping model init.
Infer image
(1, 256, 256, 1)
" keras-modelmodel-transventricular-v3.keras "
"
string(2416) "2024-06-09 22:57:14.361024: I tensorflow/core/util/port.cc:113] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.
...
Traceback (most recent call last):
File "D:pathtoinfer.py", line 220, in <module>
infer_image("input.dat")
File "D:pathtoinfer.py", line 201, in infer_image
prediction = model.predict(images)
File "C:pathtopythonlibencodingscp1252.py", line 19, in encode
return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode characters in position 19-38: character maps to <undefined>
</code>
<code>int(1)
string(183) "Init model
Model already exists in keras-model/model-transventricular-v3.keras, skipping model init.
Infer image
(1, 256, 256, 1)
" keras-modelmodel-transventricular-v3.keras "
"
string(2416) "2024-06-09 22:57:14.361024: I tensorflow/core/util/port.cc:113] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.
...
Traceback (most recent call last):
File "D:pathtoinfer.py", line 220, in <module>
infer_image("input.dat")
File "D:pathtoinfer.py", line 201, in infer_image
prediction = model.predict(images)
File "C:pathtopythonlibencodingscp1252.py", line 19, in encode
return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode characters in position 19-38: character maps to <undefined>
</code>
int(1)
string(183) "Init model
Model already exists in keras-model/model-transventricular-v3.keras, skipping model init.
Infer image
(1, 256, 256, 1)
" keras-modelmodel-transventricular-v3.keras "
"
string(2416) "2024-06-09 22:57:14.361024: I tensorflow/core/util/port.cc:113] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.
...
Traceback (most recent call last):
File "D:pathtoinfer.py", line 220, in <module>
infer_image("input.dat")
File "D:pathtoinfer.py", line 201, in infer_image
prediction = model.predict(images)
File "C:pathtopythonlibencodingscp1252.py", line 19, in encode
return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode characters in position 19-38: character maps to <undefined>
Direct Command Line Execution (Works Fine):
<code>(.venv) D:pathtoproject>..venvScriptsactivate && ..venvScriptspython.exe infer.py
2024-06-09 22:56:04.593392: I tensorflow/core/util/port.cc:113] oneDNN custom operations are on.
...
Init model
Model already exists in keras-model/model-transventricular-v3.keras, skipping model init.
Infer image
(1, 256, 256, 1)
I0000 00:00:1717948579.475089 18516 service.cc:153] StreamExecutor device (0): Host, Default Version
2024-06-09 22:56:19.530820: I tensorflow/compiler/mlir/tensorflow/utils/dump_mlir_util.cc:268] disabling MLIR crash reproducer, set env var `MLIR_CRASH_REPRODUCER_DIRECTORY` to enable.
I0000 00:00:1717948580.392302 18516 device_compiler.h:188] Compiled cluster using XLA! This line is logged at most once for the lifetime of the process.
1/1 ━━━━━━━━━━━━━━━━━━━━ 2s 2s/step
</code>
<code>(.venv) D:pathtoproject>..venvScriptsactivate && ..venvScriptspython.exe infer.py
2024-06-09 22:56:04.593392: I tensorflow/core/util/port.cc:113] oneDNN custom operations are on.
...
Init model
Model already exists in keras-model/model-transventricular-v3.keras, skipping model init.
Infer image
(1, 256, 256, 1)
I0000 00:00:1717948579.475089 18516 service.cc:153] StreamExecutor device (0): Host, Default Version
2024-06-09 22:56:19.530820: I tensorflow/compiler/mlir/tensorflow/utils/dump_mlir_util.cc:268] disabling MLIR crash reproducer, set env var `MLIR_CRASH_REPRODUCER_DIRECTORY` to enable.
I0000 00:00:1717948580.392302 18516 device_compiler.h:188] Compiled cluster using XLA! This line is logged at most once for the lifetime of the process.
1/1 ━━━━━━━━━━━━━━━━━━━━ 2s 2s/step
</code>
(.venv) D:pathtoproject>..venvScriptsactivate && ..venvScriptspython.exe infer.py
2024-06-09 22:56:04.593392: I tensorflow/core/util/port.cc:113] oneDNN custom operations are on.
...
Init model
Model already exists in keras-model/model-transventricular-v3.keras, skipping model init.
Infer image
(1, 256, 256, 1)
I0000 00:00:1717948579.475089 18516 service.cc:153] StreamExecutor device (0): Host, Default Version
2024-06-09 22:56:19.530820: I tensorflow/compiler/mlir/tensorflow/utils/dump_mlir_util.cc:268] disabling MLIR crash reproducer, set env var `MLIR_CRASH_REPRODUCER_DIRECTORY` to enable.
I0000 00:00:1717948580.392302 18516 device_compiler.h:188] Compiled cluster using XLA! This line is logged at most once for the lifetime of the process.
1/1 ━━━━━━━━━━━━━━━━━━━━ 2s 2s/step
Python Script (infer.py):
<code># imports and other code
if __name__ == '__main__':
if not os.path.exists('input.dat'):
print("input.dat not exists")
exit(0)
print("Init model")
init_model()
print("Infer image")
infer_image("input.dat")
def infer_image(image_filepath):
# Preprocess image
images = preproces(image_filepath)
print(images.shape)
path = os.path.join('keras-model', 'model-transventricular-v3.keras')
print('"', path, '"')
# load model
model = load_model(path)
# Predict image
prediction = model.predict(images)
predictions = np.argmax(prediction, axis=1)
# further processing
</code>
<code># imports and other code
if __name__ == '__main__':
if not os.path.exists('input.dat'):
print("input.dat not exists")
exit(0)
print("Init model")
init_model()
print("Infer image")
infer_image("input.dat")
def infer_image(image_filepath):
# Preprocess image
images = preproces(image_filepath)
print(images.shape)
path = os.path.join('keras-model', 'model-transventricular-v3.keras')
print('"', path, '"')
# load model
model = load_model(path)
# Predict image
prediction = model.predict(images)
predictions = np.argmax(prediction, axis=1)
# further processing
</code>
# imports and other code
if __name__ == '__main__':
if not os.path.exists('input.dat'):
print("input.dat not exists")
exit(0)
print("Init model")
init_model()
print("Infer image")
infer_image("input.dat")
def infer_image(image_filepath):
# Preprocess image
images = preproces(image_filepath)
print(images.shape)
path = os.path.join('keras-model', 'model-transventricular-v3.keras')
print('"', path, '"')
# load model
model = load_model(path)
# Predict image
prediction = model.predict(images)
predictions = np.argmax(prediction, axis=1)
# further processing