从 PHP 运行 Python 脚本
- 2024-12-03 08:45:00
- admin 原创
- 146
问题描述:
我正在尝试使用以下命令从 PHP 运行 Python 脚本:
exec('/usr/bin/python2.7 /srv/http/assets/py/switch.py arg1 arg2');
但是,PHP 根本没有产生任何输出。错误报告设置为 E_ALL,并且 display_errors 已打开。
这是我尝试过的:
我用
python2
,/usr/bin/python2
而python2.7
不是/usr/bin/python2.7
我还使用了相对路径而不是绝对路径,这也没有改变任何东西。
我尝试使用命令
exec
,shell_exec
,system
。
但是,如果我跑
if (exec('echo TEST') == 'TEST')
{
echo 'exec works!';
}
shutdown now
尽管它什么也不做,但却运行正常。
PHP 具有访问和执行该文件的权限。
编辑:感谢 Alejandro,我能够修复该问题。如果您遇到同样的问题,请不要忘记您的 Web 服务器可能/希望不是以 root 身份运行。尝试以 Web 服务器的用户或具有类似权限的用户身份登录,然后尝试自己运行命令。
解决方案 1:
在 Ubuntu Server 10.04 上测试。希望它也能在 Arch Linux 上帮到你。
在 PHP 中使用 shell_exec 函数:
通过 shell 执行命令并以字符串形式返回完整的输出。
它返回执行命令的输出,如果发生错误或命令没有产生输出则返回 NULL。
<?php
$command = escapeshellcmd('/usr/custom/test.py');
$output = shell_exec($command);
echo $output;
?>
进入 Python 文件test.py
,验证第一行中的以下文本:(参见 shebang 解释):
#!/usr/bin/env python
如果您安装了多个版本的 Python,/usr/bin/env 将确保使用的解释器是您环境的 $PATH 中的第一个。另一种方法是硬编码 #!/usr/bin/python 之类的内容;这没问题,但灵活性较差。
在 Unix 中,需要解释的可执行文件可以通过在第一行开头使用 #! 来指示要使用的解释器,后面跟着解释器(以及它可能需要的任何标志)。
当然,如果您谈论的是其他平台,则此规则不适用(但“shebang line”不会造成任何危害,而且如果您将该脚本复制到具有 Unix 基础的平台(例如 Linux、Mac 等),它会有所帮助)。
这适用于在 Unix 中通过使其可执行(chmod +x myscript.py)然后直接运行它:./myscript.py,而不仅仅是 python myscript.py
要使文件在 unix 类型平台上可执行:
chmod +x myscript.py
此外,Python 文件必须具有正确的权限(如果 PHP 脚本在浏览器或 curl 中运行,则用户 www-data / apache 可执行)和/或必须是“可执行的”。此外,.py
文件中的所有命令都必须具有正确的权限。
摘自php 手册:
对于那些试图在 unix 类型平台上使用 shell_exec 但似乎无法使其工作的人来说,这只是一个快速提醒。PHP 以系统上的 Web 用户身份执行(对于 Apache 通常是 www),因此您需要确保 Web 用户有权访问您尝试在 shell_exec 命令中使用的任何文件或目录。否则,它似乎不会执行任何操作。
解决方案 2:
我建议passthru
直接使用和处理输出缓冲区:
ob_start();
passthru('/usr/bin/python2.7 /srv/http/assets/py/switch.py arg1 arg2');
$output = ob_get_clean();
解决方案 3:
如果您想知道命令的返回状态并获取整个stdout
输出,您实际上可以使用exec
:
$command = 'ls';
exec($command, $out, $status);
$out
是所有行的数组。$status
是返回状态。对于调试非常有用。
如果你还想查看stderr
输出,你可以使用proc_open或简单地添加2>&1
到你的$command
。后者通常足以使事情正常运转,并且“实施”速度更快。
解决方案 4:
根据情况明确使用哪个命令
exec()
- 执行外部程序
system()
- 执行外部程序并显示输出
passthru()
- 执行外部程序并显示原始输出
来源: http: //php.net/manual/en/function.exec.php
解决方案 5:
Alejandro 指出了这一点,并对例外情况(Ubuntu 或 Debian)进行了澄清 - 我没有代表可以添加到答案本身:
sudoers文件:sudo visudo
添加的例外情况:www-data ALL=(ALL) NOPASSWD: ALL
解决方案 6:
在我的例子中,我需要在www
目录中创建一个名为 的新文件夹scripts
。在其中scripts
我添加了一个名为 的新文件test.py
。
然后我使用sudo chown www-data:root scripts
和sudo chown www-data:root test.py
。
然后我进入新scripts
目录并使用sudo chmod +x test.py
。
我的 test.py 文件如下所示。请注意不同的 Python 版本:
#!/usr/bin/env python3.5
print("Hello World!")
我现在从 php 执行以下操作:
$message = exec("/var/www/scripts/test.py 2>&1");
print_r($message);
您应该看到:Hello World!
解决方案 7:
以上方法看上去比较复杂,可以参考我的方法。
我有这两个文件:
运行.php
创建目录
这里,我创建了一个包含GO
按钮的 HTML 页面。每当您按下此按钮时,都会在您指定的路径下创建一个新文件夹。
运行.php
<html>
<body>
<head>
<title>
run
</title>
</head>
<form method="post">
<input type="submit" value="GO" name="GO">
</form>
</body>
</html>
<?php
if(isset($_POST['GO']))
{
shell_exec("python /var/www/html/lab/mkdir.py");
echo"success";
}
?>
运行代码片段Hide results展开片段
创建目录
#!/usr/bin/env python
import os
os.makedirs("thisfolder");
解决方案 8:
受到 Alejandro Quiroz 的启发:
<?php
$command = escapeshellcmd('python test.py');
$output = shell_exec($command);
echo $output;
?>
需要添加Python,不需要路径。
解决方案 9:
上述所有选项都会创建新的系统进程。这是一场性能噩梦。为此,我将 PHP 模块与“透明”的 Python 调用结合在一起。
https://github.com/kirmorozov/runpy
编译起来可能有点棘手,但可以节省系统进程并让您在 PHP 调用之间保持 Python 运行时间。
解决方案 10:
这很简单,但我只是想帮助那些已经遵循 Alejandro 的建议但遇到此错误的人:
sh:blabla.py:未找到命令
如果有人遇到该错误,那么 Alejandro 需要对 php 文件进行一些更改:
$command = escapeshellcmd('python blabla.py');
解决方案 11:
我确实从上面的答案中找到了对我的情况的一些帮助。对我来说,python 文件没有被调用,因为我正在使用一些旧版本的服务器,并且我创建了我正在工作的虚拟环境(包含所有必需的库)。所以我这样调用它:
$command="/home/userName/venv/bin/python /var/www/html/foldername1/foldername2/test.py"." ".$arg1." ".$arg2." ".$arg2; \\pass argument if needed in arg1 etc.
chdir("/var/www/html/folder1/folder2/"); //Changed the directory to where my files were
$output=shell_exec($command); //Execute the command in this directory
chdir("to the original working directory");
希望这对某人有帮助。
附言:由于我们的实验室已授权访问互联网,因此在服务器上单独运行这些文件(python 脚本)时,它们会卡在下载任何模块之间或出现 SSL 错误等,因此只需授予服务器互联网访问权限,它就可以正常工作。然后我从 PHP 调用它。谢谢