You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP中shell_exec循环调用Python失效 AJAX请求py返回源码不执行求助

问题排查与解决方案

问题1:PHP中shell_exec在for循环内调用Python脚本执行失败

故障原因

  • 路径不匹配:shell_exec执行时的工作目录与PHP脚本目录不一致,使用相对路径无法定位Python脚本或Python解释器
  • 权限不足:PHP运行用户(通常为www-data)无Python脚本执行权限,也无脚本依赖资源(串口、数据库、文件目录)的访问权限
  • 阻塞超时:你的Python脚本内置死循环逻辑,shell_exec默认会等待脚本执行结束再返回,导致for循环完全卡住
  • 无错误日志:默认只捕获标准输出,错误信息无留存无法定位具体问题

解决方案

  1. 调用时使用全路径,同时开启日志记录并后台运行,避免阻塞PHP:
    shell_exec('/usr/bin/python3 /你的脚本绝对路径/projet.py > /tmp/py_exec.log 2>&1 &')
    路径可通过which python3和pwd命令分别获取Python解释器和脚本的绝对路径,执行后可查看/tmp/py_exec.log文件定位具体报错
  2. 配置权限:
    执行命令给脚本加执行权限:chmod +x /你的脚本绝对路径/projet.py
    给串口开放访问权限(临时测试用):chmod 777 /dev/ttyACM0,生产环境可将PHP运行用户加入dialout用户组
  3. for循环内多次调用时必须加后台运行标记&,否则前一个脚本未退出,后续调用永远不会执行

问题2:AJAX请求返回Python源码而非执行结果

故障原因

  • 你直接将AJAX的请求地址指向.py静态文件,Web服务器(Nginx/Apache)默认无Python脚本执行能力,会将其作为纯文本文件返回源码
  • 前端代码存在语法错误:success回调中使用的output变量未定义,应改为回调参数response
  • 你的Python脚本未符合CGI/FastCGI规范,就算配置Web服务器执行Python,也无法正确返回响应内容给前端

解决方案

推荐适配现有PHP环境的最简方案:通过PHP接口转发调用Python脚本,不要直接请求.py文件

  1. 新增PHP接口文件run_py.php,代码如下:
<?php
// 防止重复启动脚本,先杀掉已存在的projet.py进程(可选)
shell_exec("pkill -f 'projet.py'");
// 后台启动Python脚本,输出日志到文件
shell_exec('/usr/bin/python3 /你的脚本绝对路径/projet.py > /tmp/py_run.log 2>&1 &');
// 返回启动状态给前端
echo json_encode(['code' => 0, 'msg' => '脚本启动成功']);
?>
  1. 修改前端AJAX代码,改为请求run_py.php:
document.getElementById("button").onclick = function () {
    $.ajax({
        type: 'POST',
        url: "run_py.php",
        data: {param: ""},
        dataType: 'json',
        success: function(response){
           console.log(response);
        }
     })
  };
  1. Python脚本优化建议:
    将串口初始化逻辑移到死循环外层,避免重复打开串口报错:
#!/usr/bin/python3
import pymysql.cursors
import time
import serial

# 初始化放在循环外
ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1)
ser.flush()
connection = pymysql.connect(host='localhost',
                             user='root',
                             password='******',
                             database='iot',
                             charset='utf8mb4',
                             cursorclass=pymysql.cursors.DictCursor)

while True :
    if ser.in_waiting > 0:
        line = ser.readline().decode('utf-8').rstrip()
        print("Valeur recu :{}".format(line))
        with connection.cursor() as cursor:
            sql = "INSERT INTO `tension` (`valeur`) VALUES (%s)"
            cursor.execute(sql, (line,))
        connection.commit()
    time.sleep(0.5)

内容的提问来源于stack exchange,提问作者koh kone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 02:15:03