MacOS下用shell_exec调用Python时如何让PHP等待执行完毕?
PHP shell_exec 执行Python脚本不等待返回的解决方法
shell_exec默认是同步阻塞执行的,出现提前返回、$result无值的问题,可按以下步骤排查修复:
- 首先给命令添加错误输出重定向,确认是否是脚本执行出错导致提前退出
shell_exec默认只会捕获标准输出(stdout)内容,Python脚本的报错信息默认输出到标准错误(stderr)不会被捕获,修改命令如下:
// 2>&1 作用是将标准错误合并到标准输出,所有输出都会进入$result $result = shell_exec('/你的Python完整绝对路径/python parser.py '.$number.'/'.$newFileName.' 2>&1');
注意:Python解释器路径务必写绝对路径,可在终端执行
which python3获取,MacOS环境下PHP默认的PATH环境变量和终端用户不一致,直接写python可能会找不到解释器导致执行失败。
- 检查命令末尾是否加了
&符,&在shell中代表后台运行,会让shell_exec直接返回,不需要后台执行的话删除该符号即可。 - 对传入的命令参数做转义处理,避免参数带空格、特殊字符导致命令解析错误提前终止:
$filePath = escapeshellarg($number.'/'.$newFileName); $result = shell_exec('/你的Python完整绝对路径/python parser.py '.$filePath.' 2>&1');
- 如果需要更可控的执行逻辑,确保100%等待进程执行完成再走后续逻辑,可以换成
proc_open函数实现:
$descriptorspec = [ 0 => ["pipe", "r"], 1 => ["pipe", "w"], 2 => ["pipe", "w"] ]; $cmd = '/你的Python完整绝对路径/python parser.py ' . escapeshellarg($number.'/'.$newFileName); $process = proc_open($cmd, $descriptorspec, $pipes); if (is_resource($process)) { fclose($pipes[0]); $result = stream_get_contents($pipes[1]); $errorInfo = stream_get_contents($pipes[2]); fclose($pipes[1]); fclose($pipes[2]); // 等待进程完全退出,获取执行状态码 $exitCode = proc_close($process); if ($exitCode !== 0) { // 此处可处理Python执行报错的逻辑,错误信息存在$errorInfo中 } }
- 最后排查权限问题,确认PHP运行的用户对Python脚本、脚本涉及读写的文件目录都有可读可写权限,权限不足也会导致脚本执行失败提前返回。
内容的提问来源于stack exchange,提问作者김성원
相关产品推荐
相关产品推荐

